agoo 2.5.4 → 2.5.5

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.

Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/bin/agoo +3 -1
  4. data/ext/agoo/base64.h +3 -3
  5. data/ext/agoo/bind.c +1 -1
  6. data/ext/agoo/bind.h +3 -3
  7. data/ext/agoo/con.c +4 -2
  8. data/ext/agoo/con.h +3 -3
  9. data/ext/agoo/debug.c +7 -0
  10. data/ext/agoo/debug.h +13 -6
  11. data/ext/agoo/doc.c +159 -0
  12. data/ext/agoo/doc.h +34 -0
  13. data/ext/agoo/dtime.h +3 -3
  14. data/ext/agoo/err.h +3 -3
  15. data/ext/agoo/error_stream.h +3 -3
  16. data/ext/agoo/extconf.rb +1 -1
  17. data/ext/agoo/gqlintro.c +333 -0
  18. data/ext/agoo/gqlintro.h +10 -0
  19. data/ext/agoo/gqlvalue.c +1035 -0
  20. data/ext/agoo/gqlvalue.h +88 -0
  21. data/ext/agoo/graphql.c +1078 -0
  22. data/ext/agoo/graphql.h +198 -0
  23. data/ext/agoo/hook.c +2 -0
  24. data/ext/agoo/hook.h +4 -3
  25. data/ext/agoo/http.c +2 -1
  26. data/ext/agoo/http.h +3 -3
  27. data/ext/agoo/kinds.h +3 -3
  28. data/ext/agoo/log.h +3 -3
  29. data/ext/agoo/log_queue.h +3 -3
  30. data/ext/agoo/method.h +3 -3
  31. data/ext/agoo/page.h +3 -3
  32. data/ext/agoo/pub.h +3 -3
  33. data/ext/agoo/queue.h +3 -3
  34. data/ext/agoo/rack_logger.h +3 -3
  35. data/ext/agoo/req.c +2 -2
  36. data/ext/agoo/req.h +3 -3
  37. data/ext/agoo/request.h +3 -3
  38. data/ext/agoo/res.h +3 -3
  39. data/ext/agoo/response.h +3 -3
  40. data/ext/agoo/rhook.c +2 -2
  41. data/ext/agoo/rhook.h +4 -3
  42. data/ext/agoo/rlog.h +3 -3
  43. data/ext/agoo/rresponse.h +3 -3
  44. data/ext/agoo/rserver.c +64 -0
  45. data/ext/agoo/rserver.h +3 -3
  46. data/ext/agoo/rupgraded.c +1 -1
  47. data/ext/agoo/rupgraded.h +3 -3
  48. data/ext/agoo/sdl.c +334 -0
  49. data/ext/agoo/sdl.h +10 -0
  50. data/ext/agoo/seg.h +3 -3
  51. data/ext/agoo/server.c +3 -1
  52. data/ext/agoo/server.h +5 -4
  53. data/ext/agoo/sha1.h +3 -3
  54. data/ext/agoo/sse.h +3 -3
  55. data/ext/agoo/sub.h +3 -3
  56. data/ext/agoo/subject.h +3 -3
  57. data/ext/agoo/text.h +3 -3
  58. data/ext/agoo/upgraded.h +3 -3
  59. data/ext/agoo/websocket.h +3 -3
  60. data/lib/agoo/version.rb +1 -1
  61. data/lib/rack/handler/agoo.rb +3 -1
  62. metadata +12 -12
  63. data/ext/agoo/foo/agoo.c +0 -109
  64. data/ext/agoo/foo/con.c +0 -1220
  65. data/ext/agoo/foo/con.h +0 -65
  66. data/ext/agoo/foo/page.c +0 -699
  67. data/ext/agoo/foo/pub.c +0 -131
  68. data/ext/agoo/foo/pub.h +0 -40
  69. data/ext/agoo/foo/rserver.c +0 -1016
  70. data/ext/agoo/foo/server.c +0 -303
  71. data/ext/agoo/foo/server.h +0 -67
  72. data/ext/agoo/foo/upgraded.c +0 -182
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8768a1d0781d3dcdfb3bd2406a1fcfb1a4a72f1f207baa209bed917fc8870bfe
4
- data.tar.gz: dd73f6588fa08dc85fbeb2e03f125d1697055eaf2bc533c9c5e175d68be50df7
3
+ metadata.gz: 409a4fe687d9ff75a67d4b25f559b5baa9df782d828bfeb1645daf696ba30035
4
+ data.tar.gz: a57f3d142cdee7c3ac6fc9d73fd05e2b1e5e4c90a1a2f276e4af0f69764f232b
5
5
  SHA512:
6
- metadata.gz: 8838e52207c0ed3c234b12e0b7468447bb3bf2f8e6ae0da777db293e3a0b2c052719a2ac825ce6151cf2e197b0d4a39c3110bbbff9c289608f95cba8f0b6fed3
7
- data.tar.gz: 850a9426c659955428c81cb516938d831e4a13e4e7c83d02923289d7b8d55635d0d2e8dcef778f53088baf6050baa634c1f3274e67469a0a42a7a23e1b958063
6
+ metadata.gz: e4f662d43b893105689f50df6a8942ec2e86e82bec8534cff159e5a5b634a5075c1a80283c474b855c41bdff208ed1f3d605ba5b98a0591bd385202a751ac884
7
+ data.tar.gz: 2fd33f0f3021820efc68a4b073526fa584ba4792d10cd25806a81b11131ffcd13d35863dc1c58a11a203f03e4d10e6943dedaf6b9f9adfbfacce97c46ea4e918
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 2.5.5 - 2018-11-12
4
+
5
+ More optimizations and some cleanup.
6
+
7
+ - New optional hint to the server that allows responses to `#call` to be cached.
8
+
9
+ - Change C header file guards. No change in behavior. Just code cleanup.
10
+
11
+ - Fixed change that slowed down the server.
12
+
3
13
  ### 2.5.4 - 2018-11-10
4
14
 
5
15
  Third times a charm.
data/bin/agoo CHANGED
@@ -46,6 +46,7 @@ Example:
46
46
  @threads = 0
47
47
  @workers = 0
48
48
  @first = false
49
+ @graphql = nil
49
50
 
50
51
  @opts = OptionParser.new(usage)
51
52
  @opts.on('-h', '--help', 'Show this display.') { puts @opts.help; Process.exit!(0) }
@@ -54,6 +55,7 @@ Example:
54
55
  @opts.on('-f', '--root_first', 'Check the root directory before the handle paths.') { @first = true }
55
56
  @opts.on('-p', '--port PORT', Integer, 'Port to listen on.') { |p| @port = p }
56
57
  @opts.on('-d', '--dir DIR', String, 'Directory to serve static assets from.') { |d| @root = d }
58
+ @opts.on('-g', '--graphql PATH', String, 'URL path for GraphQL requests.') { |g| @graphql = g }
57
59
  @opts.on('-r', '--require FILE', String, 'Ruby require.') { |r| require r }
58
60
  @opts.on('-t', '--threads COUNT', Integer, 'Number of threads to use.') { |t| @threads = t }
59
61
  @opts.on('-w', '--workers COUNT', Integer, 'Number of workers to use.') { |w| @workers = w }
@@ -81,7 +83,7 @@ Agoo::Log.configure(dir: @log_dir,
81
83
  push: 2 <= @verbose,
82
84
  })
83
85
 
84
- Agoo::Server.init(@port, @root, thread_count: @threads, worker_count: @workers, root_first: @first)
86
+ Agoo::Server.init(@port, @root, thread_count: @threads, worker_count: @workers, root_first: @first, graphql: @graphql)
85
87
 
86
88
  puts "Agoo #{Agoo::VERSION} is listening on port #{@port}. Path mappings are:" if 1 <= @verbose
87
89
 
@@ -1,7 +1,7 @@
1
1
  // Copyright 2011, 2016, 2018 by Peter Ohler, All Rights Reserved
2
2
 
3
- #ifndef __AGOO_BASE64_H__
4
- #define __AGOO_BASE64_H__
3
+ #ifndef AGOO_BASE64_H
4
+ #define AGOO_BASE64_H
5
5
 
6
6
  typedef unsigned char uchar;
7
7
 
@@ -12,4 +12,4 @@ extern unsigned long b64_orig_size(const char *text);
12
12
  extern int b64_to(const uchar *src, int len, char *b64);
13
13
  extern void b64_from(const char *b64, uchar *str);
14
14
 
15
- #endif /* __AGOO_BASE64_H__ */
15
+ #endif // AGOO_BASE64_H
@@ -193,7 +193,7 @@ bind_url(Err err, const char *url) {
193
193
  char scheme[8];
194
194
 
195
195
  if (NULL != colon && colon - url < (int)sizeof(scheme)) {
196
- int slen = colon - url;
196
+ int slen = (int)(colon - url);
197
197
 
198
198
  memcpy(scheme, url, slen);
199
199
  scheme[slen] = '\0';
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
- #ifndef __AGOO_BIND_H__
4
- #define __AGOO_BIND_H__
3
+ #ifndef AGOO_BIND_H
4
+ #define AGOO_BIND_H
5
5
 
6
6
  #include <stdbool.h>
7
7
  #include <sys/socket.h>
@@ -41,4 +41,4 @@ extern void bind_destroy(Bind b);
41
41
  extern int bind_listen(Err err, Bind b);
42
42
  extern void bind_close(Bind b);
43
43
 
44
- #endif // __AGOO_BIND_H__
44
+ #endif // AGOO_BIND_H
@@ -974,8 +974,10 @@ short
974
974
  con_http_events(Con c) {
975
975
  short events = 0;
976
976
 
977
- if ((NULL != c->res_head && NULL != res_message(c->res_head)) || !c->closing) {
977
+ if (NULL != c->res_head && NULL != res_message(c->res_head)) {
978
978
  events = POLLIN | POLLOUT;
979
+ } else if (!c->closing) {
980
+ events = POLLIN;
979
981
  }
980
982
  return events;
981
983
  }
@@ -1142,7 +1144,7 @@ con_loop(void *x) {
1142
1144
  goto CON_CHECK;
1143
1145
  }
1144
1146
  }
1145
- if (0 != (pp->revents & POLLOUT) && NULL != c->res_head && NULL != res_message(c->res_head)) {
1147
+ if (0 != (pp->revents & POLLOUT)) {
1146
1148
  if (con_write(c)) {
1147
1149
  c->dead = true;
1148
1150
  goto CON_CHECK;
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
- #ifndef __AGOO_CON_H__
4
- #define __AGOO_CON_H__
3
+ #ifndef AGOO_CON_H
4
+ #define AGOO_CON_H
5
5
 
6
6
  #include <poll.h>
7
7
  #include <pthread.h>
@@ -62,4 +62,4 @@ extern bool con_http_read(Con c);
62
62
  extern bool con_http_write(Con c);
63
63
  extern short con_http_events(Con c);
64
64
 
65
- #endif /* __AGOO_CON_H__ */
65
+ #endif /* AGOO_CON_H */
@@ -28,6 +28,13 @@ atomic_int mem_cslot = 0;
28
28
  atomic_int mem_err_stream = 0;
29
29
  atomic_int mem_eval_threads = 0;
30
30
  atomic_int mem_group = 0;
31
+ atomic_int mem_graphql_arg = 0;
32
+ atomic_int mem_graphql_directive = 0;
33
+ atomic_int mem_graphql_field = 0;
34
+ atomic_int mem_graphql_link = 0;
35
+ atomic_int mem_graphql_slot = 0;
36
+ atomic_int mem_graphql_type = 0;
37
+ atomic_int mem_graphql_value = 0;
31
38
  atomic_int mem_group_path = 0;
32
39
  atomic_int mem_header = 0;
33
40
  atomic_int mem_hook = 0;
@@ -1,14 +1,14 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
- #ifndef __AGOO_DEBUG_H__
4
- #define __AGOO_DEBUG_H__
3
+ #ifndef AGOO_DEBUG_H
4
+ #define AGOO_DEBUG_H
5
5
 
6
6
  #include <stdatomic.h>
7
7
 
8
8
  #ifdef MEM_DEBUG
9
- #define DEBUG_ALLOC(var, ptr) { atomic_fetch_add(&var, 1); debug_add(ptr, #var, __FILE__, __LINE__); }
10
- #define DEBUG_REALLOC(var, orig, ptr) { debug_update(orig, ptr, #var, __FILE__, __LINE__); }
11
- #define DEBUG_FREE(var, ptr) { atomic_fetch_sub(&var, 1); debug_del(ptr, __FILE__, __LINE__); }
9
+ #define DEBUG_ALLOC(var, ptr) { atomic_fetch_add(&var, 1); debug_add(ptr, #var, FILE, LINE); }
10
+ #define DEBUG_REALLOC(var, orig, ptr) { debug_update(orig, ptr, #var, FILE, LINE); }
11
+ #define DEBUG_FREE(var, ptr) { atomic_fetch_sub(&var, 1); debug_del(ptr, FILE, LINE); }
12
12
  #else
13
13
  #define DEBUG_ALLOC(var, ptr) { }
14
14
  #define DEBUG_REALLOC(var, orig, ptr) { }
@@ -21,6 +21,13 @@ extern atomic_int mem_con;
21
21
  extern atomic_int mem_cslot;
22
22
  extern atomic_int mem_err_stream;
23
23
  extern atomic_int mem_eval_threads;
24
+ extern atomic_int mem_graphql_arg;
25
+ extern atomic_int mem_graphql_directive;
26
+ extern atomic_int mem_graphql_field;
27
+ extern atomic_int mem_graphql_link;
28
+ extern atomic_int mem_graphql_slot;
29
+ extern atomic_int mem_graphql_type;
30
+ extern atomic_int mem_graphql_value;
24
31
  extern atomic_int mem_group;
25
32
  extern atomic_int mem_group_path;
26
33
  extern atomic_int mem_header;
@@ -54,4 +61,4 @@ extern void debug_del(void *ptr, const char *file, int line);
54
61
  extern void debug_report();
55
62
  extern void debug_rreport(); // when called from ruby
56
63
 
57
- #endif /* __AGOO_DEBUG_H__ */
64
+ #endif /* AGOO_DEBUG_H */
@@ -0,0 +1,159 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdbool.h>
4
+ #include <stdint.h>
5
+ #include <stdio.h>
6
+ #include <string.h>
7
+
8
+ #include "doc.h"
9
+ #include "gqlvalue.h"
10
+
11
+ static char char_map[256] = "\
12
+ .........ww..w..................\
13
+ wpq.....pp..w.p.ttttttttttp..p..\
14
+ pttttttttttttttttttttttttttp.p.t\
15
+ .ttttttttttttttttttttttttttppp..\
16
+ ................................\
17
+ ................................\
18
+ ................................\
19
+ ................................";
20
+
21
+ void
22
+ doc_init(Doc doc, const char *str, int len) {
23
+ if (0 >= len) {
24
+ len = (int)strlen(str);
25
+ }
26
+ doc->str = str;
27
+ doc->cur = str;
28
+ doc->end = str + len;
29
+ // If there is a BOM, skip it.
30
+ if (0xEF == (uint8_t)*doc->str && 0xBB == (uint8_t)doc->str[1] && 0xBF == (uint8_t)doc->str[2]) {
31
+ doc->cur += 3;
32
+ }
33
+ }
34
+
35
+ int
36
+ doc_skip_white(Doc doc) {
37
+ const char *start = doc->cur;
38
+
39
+ for (; 'w' == char_map[*(uint8_t*)doc->cur]; doc->cur++) {
40
+ }
41
+ return (int)(doc->cur - start);
42
+ }
43
+
44
+ void
45
+ doc_skip_comment(Doc doc) {
46
+ for (; true; doc->cur++) {
47
+ switch (*doc->cur) {
48
+ case '\r':
49
+ case '\n':
50
+ return;
51
+ default:
52
+ break;
53
+ }
54
+ }
55
+ }
56
+
57
+ void
58
+ doc_read_token(Doc doc) {
59
+ if ('t' == char_map[*(uint8_t*)doc->cur] && '9' < *doc->cur) {
60
+ doc->cur++;
61
+ for (; 't' == char_map[*(uint8_t*)doc->cur]; doc->cur++) {
62
+ }
63
+ }
64
+ }
65
+
66
+ void
67
+ doc_next_token(Doc doc) {
68
+ while (true) {
69
+ doc_skip_white(doc);
70
+ if ('#' == *doc->cur) {
71
+ doc_skip_comment(doc);
72
+ } else {
73
+ break;
74
+ }
75
+ }
76
+ }
77
+
78
+ // Just find end.
79
+ int
80
+ doc_read_string(Err err, Doc doc) {
81
+ doc->cur++; // skip first "
82
+ if ('"' == *doc->cur) { // a """ string or an empty string
83
+ doc->cur++;
84
+ if ('"' != *doc->cur) {
85
+ return ERR_OK; // empty string
86
+ }
87
+ doc->cur++;
88
+ for (; doc->cur < doc->end; doc->cur++) {
89
+ if ('"' == *doc->cur && '"' == doc->cur[1] && '"' == doc->cur[2]) {
90
+ doc->cur += 3;
91
+ break;
92
+ }
93
+ }
94
+ } else {
95
+ for (; doc->cur < doc->end; doc->cur++) {
96
+ if ('"' == *doc->cur) {
97
+ if ('\\' != doc->cur[-1]) {
98
+ doc->cur++;
99
+ break;
100
+ }
101
+ }
102
+ }
103
+ }
104
+ if (doc->end <= doc->cur) {
105
+ return doc_err(doc, err, "String not terminated");
106
+ }
107
+ return ERR_OK;
108
+ }
109
+
110
+ int
111
+ doc_err(Doc doc, Err err, const char *fmt, ...) {
112
+ va_list ap;
113
+ char msg[248];
114
+ int line = 0;
115
+ int col = 0;
116
+
117
+ va_start(ap, fmt);
118
+ vsnprintf(msg, sizeof(msg), fmt, ap);
119
+ doc_location(doc, &line, &col);
120
+ va_end(ap);
121
+
122
+ return err_set(err, ERR_PARSE, "%s at %d:%d", msg, line, col);
123
+ }
124
+
125
+ void
126
+ doc_location(Doc doc, int *linep, int *colp) {
127
+ const char *s;
128
+ int line = 1;
129
+ int col = 1;
130
+
131
+ for (s = doc->str; s < doc->cur; s++) {
132
+ switch (*s) {
133
+ case '\n':
134
+ line++;
135
+ col = 1;
136
+ break;
137
+ case '\r':
138
+ if ('\n' == *(s + 1)) {
139
+ s++;
140
+ }
141
+ line++;
142
+ col = 1;
143
+ break;
144
+ default:
145
+ col++;
146
+ break;
147
+ }
148
+ }
149
+ *linep = line;
150
+ *colp = col;
151
+ }
152
+
153
+ gqlValue
154
+ doc_read_value(Err err, Doc doc) {
155
+ // TBD handle list and object as well as scalars, object is typeless
156
+ // TBD put this in doc_read_value
157
+ return NULL;
158
+ }
159
+
@@ -0,0 +1,34 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef AGOO_DOC_H
4
+ #define AGOO_DOC_H
5
+
6
+ #include <stdarg.h>
7
+
8
+ #include "err.h"
9
+
10
+ struct _gqlValue;
11
+
12
+ typedef struct _Doc {
13
+ const char *str;
14
+ const char *cur;
15
+ const char *end;
16
+ } *Doc;
17
+
18
+ extern void doc_init(Doc doc, const char *str, int len);
19
+
20
+ extern int doc_skip_white(Doc doc);
21
+ extern void doc_skip_comment(Doc doc);
22
+ extern int doc_read_desc(Err err, Doc doc);
23
+
24
+ extern void doc_next_token(Doc doc);
25
+ extern void doc_read_token(Doc doc);
26
+
27
+ extern int doc_read_string(Err err, Doc doc);
28
+
29
+ extern int doc_err(Doc doc, Err err, const char *fmt, ...);
30
+ extern void doc_location(Doc doc, int *linep, int *colp);
31
+
32
+ extern struct _gqlValue* doc_read_value(Err err, Doc doc);
33
+
34
+ #endif // AGOO_DOC_H
@@ -1,10 +1,10 @@
1
1
  // Copyright 2009, 2015, 2018, 2016 by Peter Ohler, All Rights Reserved
2
2
 
3
- #ifndef __AGOO_DTIME_H__
4
- #define __AGOO_DTIME_H__
3
+ #ifndef AGOO_DTIME_H
4
+ #define AGOO_DTIME_H
5
5
 
6
6
  extern double dtime(void);
7
7
  extern double dsleep(double t);
8
8
  extern double dwait(double t);
9
9
 
10
- #endif /* __AGOO_DTIME_H__ */
10
+ #endif /* AGOO_DTIME_H */
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
- #ifndef __AGOO_ERR_H__
4
- #define __AGOO_ERR_H__
3
+ #ifndef AGOO_ERR_H
4
+ #define AGOO_ERR_H
5
5
 
6
6
  #include <errno.h>
7
7
 
@@ -42,4 +42,4 @@ extern int err_no(Err err, const char *fmt, ...);
42
42
  extern const char* err_str(ErrCode code);
43
43
  extern void err_clear(Err err);
44
44
 
45
- #endif /* __AGOO_ERR_H__ */
45
+ #endif /* AGOO_ERR_H */
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
- #ifndef __AGOO_ERROR_STREAM_H__
4
- #define __AGOO_ERROR_STREAM_H__
3
+ #ifndef AGOO_ERROR_STREAM_H
4
+ #define AGOO_ERROR_STREAM_H
5
5
 
6
6
  #include <ruby.h>
7
7
 
@@ -10,4 +10,4 @@
10
10
  extern void error_stream_init(VALUE mod);
11
11
  extern VALUE error_stream_new();
12
12
 
13
- #endif // __AGOO_ERROR_STREAM_H__
13
+ #endif // AGOO_ERROR_STREAM_H
@@ -4,7 +4,7 @@ require 'rbconfig'
4
4
  extension_name = 'agoo'
5
5
  dir_config(extension_name)
6
6
 
7
- $CPPFLAGS += " -DPLATFORM_LINUX" if 'x86_64-linux' == RUBY_PLATFORM
7
+ $CFLAGS += " -DPLATFORM_LINUX" if 'x86_64-linux' == RUBY_PLATFORM
8
8
 
9
9
  # Adding the __attribute__ flag only works with gcc compilers and even then it
10
10
  # does not work to check args with varargs s just remove the check.
@@ -0,0 +1,333 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+
6
+ #include "gqlintro.h"
7
+ #include "gqlvalue.h"
8
+ #include "graphql.h"
9
+
10
+ static gqlType schema_type;
11
+ static gqlType type_type;
12
+ static gqlType type_kind_type;
13
+ static gqlType field_type;
14
+ static gqlType input_value_type;
15
+ static gqlType enum_value_type;
16
+ static gqlType directive_type;
17
+ static gqlType directive_location_type;
18
+
19
+ // type __Schema {
20
+ // types: [__Type!]!
21
+ // queryType: __Type!
22
+ // mutationType: __Type
23
+ // subscriptionType: __Type
24
+ // directives: [__Directive!]!
25
+ // }
26
+ static gqlRef
27
+ schema_types_resolve(gqlRef target, const char *fieldName, gqlKeyVal *args) {
28
+ // TBD
29
+ return NULL;
30
+ }
31
+
32
+ static gqlRef
33
+ schema_query_type_resolve(gqlRef target, const char *fieldName, gqlKeyVal *args) {
34
+ // TBD return schema_type.query.type
35
+ // lookup "schema" type
36
+ // get query field
37
+ // get return type of field
38
+ return NULL;
39
+ }
40
+
41
+ static int
42
+ create_schema_type(Err err) {
43
+ if (NULL == (schema_type = gql_type_create(err, "__Schema", NULL, -1, true, NULL)) ||
44
+ NULL == gql_type_field(err, schema_type, "types", type_type, NULL, true, true, true, schema_types_resolve) ||
45
+ NULL == gql_type_field(err, schema_type, "queryType", type_type, NULL, true, false, false, schema_query_type_resolve) ||
46
+ NULL == gql_type_field(err, schema_type, "mutationType", type_type, NULL, false, false, false, NULL) ||
47
+ NULL == gql_type_field(err, schema_type, "subscriptionType", type_type, NULL, false, false, false, NULL) ||
48
+ NULL == gql_type_field(err, schema_type, "directives", directive_type, NULL, true, true, true, NULL)) {
49
+
50
+ return err->code;
51
+ }
52
+ schema_type->core = true;
53
+
54
+ return ERR_OK;
55
+ }
56
+
57
+ // type __Type {
58
+ // kind: __TypeKind!
59
+ // name: String
60
+ // description: String
61
+ // fields(includeDeprecated: Boolean = false): [__Field!]
62
+ // interfaces: [__Type!]
63
+ // possibleTypes: [__Type!]
64
+ // enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
65
+ // inputFields: [__InputValue!]
66
+ // ofType: __Type
67
+ // }
68
+ static int
69
+ create_type_type(Err err) {
70
+ gqlField fields = NULL;
71
+ gqlField enum_values = NULL;
72
+ gqlValue dv;
73
+
74
+ if (NULL == (type_type = gql_type_create(err, "__Type", NULL, -1, true, NULL)) ||
75
+ NULL == gql_type_field(err, type_type, "kind", type_kind_type, NULL, true, false, false, NULL) ||
76
+ NULL == gql_type_field(err, type_type, "name", &gql_string_type, NULL, false, false, false, NULL) ||
77
+ NULL == gql_type_field(err, type_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
78
+ NULL == (fields = gql_type_field(err, type_type, "fields", field_type, NULL, false, true, true, NULL)) ||
79
+ NULL == gql_type_field(err, type_type, "interfaces", type_type, NULL, false, true, true, NULL) ||
80
+ NULL == gql_type_field(err, type_type, "possibleTypes", type_type, NULL, false, true, true, NULL) ||
81
+ NULL == (enum_values = gql_type_field(err, type_type, "enumValues", enum_value_type, NULL, false, true, true, NULL)) ||
82
+ NULL == gql_type_field(err, type_type, "inputFields", input_value_type, NULL, false, true, true, NULL) ||
83
+ NULL == gql_type_field(err, type_type, "ofType", type_type, NULL, false, false, false, NULL)) {
84
+
85
+ return err->code;
86
+ }
87
+ type_type->core = true;
88
+
89
+ if (NULL == (dv = gql_bool_create(err, false)) ||
90
+ NULL == gql_field_arg(err, fields, "includeDeprecated", &gql_bool_type, NULL, dv, false) ||
91
+ NULL == (dv = gql_bool_create(err, false)) ||
92
+ NULL == gql_field_arg(err, enum_values, "includeDeprecated", &gql_bool_type, NULL, dv, false)) {
93
+
94
+ return err->code;
95
+ }
96
+ return ERR_OK;
97
+ }
98
+
99
+ static int
100
+ create_type_kind_type(Err err) {
101
+ const char *choices[] = {
102
+ "SCALAR",
103
+ "OBJECT",
104
+ "INTERFACE",
105
+ "UNION",
106
+ "ENUM",
107
+ "INPUT_OBJECT",
108
+ "LIST",
109
+ "NON_NULL",
110
+ NULL
111
+ };
112
+ const char **cp;
113
+
114
+ type_kind_type = gql_enum_create(err, "__TypeKind", NULL, -1, true);
115
+ type_kind_type->core = true;
116
+ for (cp = choices; NULL != *cp; cp++) {
117
+ if (ERR_OK != gql_enum_append(err, type_kind_type, *cp, -1)) {
118
+ return err->code;
119
+ }
120
+ }
121
+ return err->code;
122
+ }
123
+
124
+ // type __Field {
125
+ // name: String!
126
+ // description: String
127
+ // args: [__InputValue!]!
128
+ // type: __Type!
129
+ // isDeprecated: Boolean!
130
+ // deprecationReason: String
131
+ // }
132
+ static int
133
+ create_field_type(Err err) {
134
+ if (NULL == (field_type = gql_type_create(err, "__Field", NULL, -1, true, NULL)) ||
135
+ NULL == gql_type_field(err, field_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
136
+ NULL == gql_type_field(err, field_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
137
+ NULL == gql_type_field(err, field_type, "args", input_value_type, NULL, true, true, true, NULL) ||
138
+ NULL == gql_type_field(err, field_type, "type", type_type, NULL, true, false, false, NULL) ||
139
+ NULL == gql_type_field(err, field_type, "isDeprecated", &gql_bool_type, NULL, true, false, false, NULL) ||
140
+ NULL == gql_type_field(err, field_type, "reason", &gql_string_type, NULL, false, false, false, NULL)) {
141
+
142
+ return err->code;
143
+ }
144
+ field_type->core = true;
145
+
146
+ return ERR_OK;
147
+ }
148
+
149
+ // type __InputValue {
150
+ // name: String!
151
+ // description: String
152
+ // type: __Type!
153
+ // defaultValue: String
154
+ // }
155
+ static int
156
+ create_input_type(Err err) {
157
+ if (NULL == (input_value_type = gql_type_create(err, "__InputValue", NULL, -1, true, NULL)) ||
158
+ NULL == gql_type_field(err, input_value_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
159
+ NULL == gql_type_field(err, input_value_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
160
+ NULL == gql_type_field(err, input_value_type, "type", type_type, NULL, true, false, false, NULL) ||
161
+ NULL == gql_type_field(err, input_value_type, "defaultValue", &gql_string_type, NULL, false, false, false, NULL)) {
162
+
163
+ return err->code;
164
+ }
165
+ input_value_type->core = true;
166
+
167
+ return ERR_OK;
168
+ }
169
+
170
+ // type __EnumValue {
171
+ // name: String!
172
+ // description: String
173
+ // isDeprecated: Boolean!
174
+ // deprecationReason: String
175
+ // }
176
+ static int
177
+ create_enum_type(Err err) {
178
+ if (NULL == (enum_value_type = gql_type_create(err, "__EnumValue", NULL, -1, true, NULL)) ||
179
+ NULL == gql_type_field(err, enum_value_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
180
+ NULL == gql_type_field(err, enum_value_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
181
+ NULL == gql_type_field(err, enum_value_type, "isDeprecated", &gql_bool_type, NULL, true, false, false, NULL) ||
182
+ NULL == gql_type_field(err, enum_value_type, "deprecationReason", &gql_string_type, NULL, false, false, false, NULL)) {
183
+
184
+ return err->code;
185
+ }
186
+ enum_value_type->core = true;
187
+
188
+ return ERR_OK;
189
+ }
190
+
191
+ // type __Directive {
192
+ // name: String!
193
+ // description: String
194
+ // locations: [__DirectiveLocation!]!
195
+ // args: [__InputValue!]!
196
+ // }
197
+ static int
198
+ create_directive_type(Err err) {
199
+ if (NULL == (directive_type = gql_type_create(err, "__Directive", NULL, -1, true, NULL)) ||
200
+ NULL == gql_type_field(err, directive_type, "name", &gql_string_type, NULL, true, false, false, NULL) ||
201
+ NULL == gql_type_field(err, directive_type, "description", &gql_string_type, NULL, false, false, false, NULL) ||
202
+ NULL == gql_type_field(err, directive_type, "location", directive_location_type, NULL, true, true, true, NULL) ||
203
+ NULL == gql_type_field(err, directive_type, "args", input_value_type, NULL, true, true, true, NULL)) {
204
+
205
+ return err->code;
206
+ }
207
+ directive_type->core = true;
208
+
209
+ return ERR_OK;
210
+ }
211
+
212
+ static int
213
+ create_directive_location_type(Err err) {
214
+ const char *choices[] = {
215
+ "QUERY",
216
+ "MUTATION",
217
+ "SUBSCRIPTION",
218
+ "FIELD",
219
+ "FRAGMENT_DEFINITION",
220
+ "FRAGMENT_SPREAD",
221
+ "INLINE_FRAGMENT",
222
+ "SCHEMA",
223
+ "SCALAR",
224
+ "OBJECT",
225
+ "FIELD_DEFINITION",
226
+ "ARGUMENT_DEFINITION",
227
+ "INTERFACE",
228
+ "UNION",
229
+ "ENUM",
230
+ "ENUM_VALUE",
231
+ "INPUT_OBJECT",
232
+ "INPUT_FIELD_DEFINITION",
233
+ NULL };
234
+ const char **cp;
235
+
236
+ directive_location_type = gql_enum_create(err, "__DirectiveLocation", NULL, -1, true);
237
+ directive_location_type->core = true;
238
+ for (cp = choices; NULL != *cp; cp++) {
239
+ if (ERR_OK != gql_enum_append(err, directive_location_type, *cp, -1)) {
240
+ return err->code;
241
+ }
242
+ }
243
+ return err->code;
244
+ }
245
+
246
+ static int
247
+ create_dir_skip(Err err) {
248
+ gqlDir dir = gql_directive_create(err, "skip", NULL, -1, true);
249
+
250
+ if (NULL == dir) {
251
+ return err->code;
252
+ }
253
+ if (ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
254
+ ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
255
+ ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
256
+ NULL == gql_dir_arg(err, dir, "if", "Boolean", NULL, -1, NULL, true)) {
257
+
258
+ return err->code;
259
+ }
260
+ return ERR_OK;
261
+ }
262
+
263
+ static int
264
+ create_dir_include(Err err) {
265
+ gqlDir dir = gql_directive_create(err, "include", NULL, -1, true);
266
+
267
+ if (NULL == dir) {
268
+ return err->code;
269
+ }
270
+ if (ERR_OK != gql_directive_on(err, dir, "FIELD", -1) ||
271
+ ERR_OK != gql_directive_on(err, dir, "FRAGMENT_SPREAD", -1) ||
272
+ ERR_OK != gql_directive_on(err, dir, "INLINE_FRAGMENT", -1) ||
273
+ NULL == gql_dir_arg(err, dir, "if", "Boolean", NULL, -1, NULL, true)) {
274
+
275
+ return err->code;
276
+ }
277
+ return ERR_OK;
278
+ }
279
+
280
+ static int
281
+ create_dir_deprecated(Err err) {
282
+ gqlDir dir = gql_directive_create(err, "deprecated", NULL, -1, true);
283
+ gqlValue dv;
284
+
285
+ if (NULL == dir) {
286
+ return err->code;
287
+ }
288
+ if (ERR_OK != gql_directive_on(err, dir, "FIELD_DEFINITION", -1) ||
289
+ ERR_OK != gql_directive_on(err, dir, "ENUM_VALUE", -1) ||
290
+ NULL == (dv = gql_string_create(err, "No longer supported", -1)) ||
291
+ NULL == gql_dir_arg(err, dir, "reason", "String", NULL, -1, dv, false)) {
292
+
293
+ return err->code;
294
+ }
295
+ return ERR_OK;
296
+ }
297
+
298
+ int
299
+ gql_intro_init(Err err) {
300
+ gqlField f;
301
+
302
+ if (ERR_OK != create_type_kind_type(err) ||
303
+ ERR_OK != create_input_type(err) ||
304
+ ERR_OK != create_type_type(err) ||
305
+ ERR_OK != create_enum_type(err) ||
306
+ ERR_OK != create_field_type(err) ||
307
+ ERR_OK != create_directive_location_type(err) ||
308
+ ERR_OK != create_directive_type(err) ||
309
+ ERR_OK != create_schema_type(err) ||
310
+ ERR_OK != create_dir_deprecated(err) ||
311
+ ERR_OK != create_dir_include(err) ||
312
+ ERR_OK != create_dir_skip(err)) {
313
+
314
+ return err->code;
315
+ }
316
+ // InputValue and Type as well Field and Type as have a depency loop so
317
+ // complete the loop.
318
+ for (f = input_value_type->fields; NULL != f; f = f->next) {
319
+ if (0 == strcmp("type", f->name)) {
320
+ f->type = type_type;
321
+ break;
322
+ }
323
+ }
324
+ for (f = type_type->fields; NULL != f; f = f->next) {
325
+ if (0 == strcmp("fields", f->name)) {
326
+ f->type = field_type;
327
+ } else if (0 == strcmp("enumValues", f->name)) {
328
+ f->type = enum_value_type;
329
+ break;
330
+ }
331
+ }
332
+ return ERR_OK;
333
+ }