agoo 2.5.7 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +38 -0
- data/ext/agoo/agoo.c +11 -2
- data/ext/agoo/bind.c +15 -20
- data/ext/agoo/con.c +32 -25
- data/ext/agoo/debug.c +225 -162
- data/ext/agoo/debug.h +31 -51
- data/ext/agoo/doc.c +278 -5
- data/ext/agoo/doc.h +6 -1
- data/ext/agoo/err.c +1 -0
- data/ext/agoo/err.h +1 -0
- data/ext/agoo/error_stream.c +3 -6
- data/ext/agoo/gqlcobj.c +12 -0
- data/ext/agoo/gqlcobj.h +25 -0
- data/ext/agoo/gqleval.c +520 -0
- data/ext/agoo/gqleval.h +49 -0
- data/ext/agoo/gqlintro.c +1237 -97
- data/ext/agoo/gqlintro.h +8 -0
- data/ext/agoo/gqljson.c +460 -0
- data/ext/agoo/gqljson.h +15 -0
- data/ext/agoo/gqlvalue.c +679 -136
- data/ext/agoo/gqlvalue.h +29 -7
- data/ext/agoo/graphql.c +841 -362
- data/ext/agoo/graphql.h +180 -90
- data/ext/agoo/hook.c +8 -16
- data/ext/agoo/http.c +3 -4
- data/ext/agoo/log.c +22 -25
- data/ext/agoo/log.h +1 -0
- data/ext/agoo/page.c +24 -40
- data/ext/agoo/pub.c +23 -21
- data/ext/agoo/queue.c +2 -4
- data/ext/agoo/ready.c +9 -9
- data/ext/agoo/req.c +80 -5
- data/ext/agoo/req.h +2 -0
- data/ext/agoo/res.c +1 -3
- data/ext/agoo/rgraphql.c +753 -0
- data/ext/agoo/rresponse.c +9 -15
- data/ext/agoo/rserver.c +18 -17
- data/ext/agoo/sdl.c +1264 -120
- data/ext/agoo/sdl.h +8 -1
- data/ext/agoo/sectime.c +136 -0
- data/ext/agoo/sectime.h +19 -0
- data/ext/agoo/server.c +1 -3
- data/ext/agoo/subject.c +2 -4
- data/ext/agoo/text.c +124 -18
- data/ext/agoo/text.h +5 -1
- data/ext/agoo/upgraded.c +2 -4
- data/lib/agoo/version.rb +1 -1
- data/test/base_handler_test.rb +43 -40
- data/test/bind_test.rb +49 -48
- data/test/graphql_test.rb +1019 -0
- data/test/hijack_test.rb +1 -1
- data/test/rack_handler_test.rb +40 -34
- data/test/static_test.rb +33 -32
- metadata +17 -6
data/ext/agoo/gqlvalue.h
CHANGED
@@ -20,14 +20,22 @@ typedef struct _gqlLink {
|
|
20
20
|
typedef struct _gqlValue {
|
21
21
|
struct _gqlType *type;
|
22
22
|
union {
|
23
|
-
char *url;
|
24
23
|
int32_t i;
|
25
24
|
int64_t i64;
|
26
25
|
double f;
|
27
26
|
bool b;
|
28
27
|
int64_t time;
|
29
|
-
|
30
|
-
|
28
|
+
union {
|
29
|
+
struct {
|
30
|
+
char alloced;
|
31
|
+
char a[15];
|
32
|
+
};
|
33
|
+
struct {
|
34
|
+
char x; // same memory location as kind
|
35
|
+
char pad[7];
|
36
|
+
const char *ptr;
|
37
|
+
};
|
38
|
+
} str;
|
31
39
|
struct {
|
32
40
|
uint64_t hi;
|
33
41
|
uint64_t lo;
|
@@ -42,11 +50,16 @@ typedef struct _gqlValue {
|
|
42
50
|
extern int gql_value_init(agooErr err);
|
43
51
|
|
44
52
|
extern void gql_value_destroy(gqlValue value);
|
53
|
+
extern gqlValue gql_value_dup(agooErr err, gqlValue value);
|
54
|
+
|
55
|
+
extern gqlLink gql_link_create(agooErr err, const char *key, gqlValue value);
|
56
|
+
extern void gql_link_destroy(gqlLink link);
|
45
57
|
|
46
58
|
extern gqlValue gql_int_create(agooErr err, int32_t i);
|
47
59
|
extern gqlValue gql_i64_create(agooErr err, int64_t i);
|
48
60
|
extern gqlValue gql_string_create(agooErr err, const char *str, int len);
|
49
|
-
extern gqlValue
|
61
|
+
extern gqlValue gql_token_create(agooErr err, const char *str, int len, struct _gqlType *type);
|
62
|
+
extern gqlValue gql_var_create(agooErr err, const char *str, int len);
|
50
63
|
extern gqlValue gql_bool_create(agooErr err, bool b);
|
51
64
|
extern gqlValue gql_float_create(agooErr err, double f);
|
52
65
|
extern gqlValue gql_time_create(agooErr err, int64_t t);
|
@@ -54,7 +67,7 @@ extern gqlValue gql_time_str_create(agooErr err, const char *str, int len);
|
|
54
67
|
extern gqlValue gql_uuid_create(agooErr err, uint64_t hi, uint64_t lo);
|
55
68
|
extern gqlValue gql_uuid_str_create(agooErr err, const char *str, int len);
|
56
69
|
extern gqlValue gql_null_create(agooErr err);
|
57
|
-
extern gqlValue gql_list_create(agooErr err, struct _gqlType *
|
70
|
+
extern gqlValue gql_list_create(agooErr err, struct _gqlType *item_type);
|
58
71
|
extern gqlValue gql_object_create(agooErr err);
|
59
72
|
|
60
73
|
extern int gql_list_append(agooErr err, gqlValue list, gqlValue item);
|
@@ -64,7 +77,7 @@ extern int gql_object_set(agooErr err, gqlValue obj, const char *key, gqlValue i
|
|
64
77
|
extern void gql_int_set(gqlValue value, int32_t i);
|
65
78
|
extern void gql_i64_set(gqlValue value, int64_t i);
|
66
79
|
extern int gql_string_set(agooErr err, gqlValue value, const char *str, int len);
|
67
|
-
extern int
|
80
|
+
extern int gql_token_set(agooErr err, gqlValue value, const char *str, int len);
|
68
81
|
extern void gql_bool_set(gqlValue value, bool b);
|
69
82
|
extern void gql_float_set(gqlValue value, double f);
|
70
83
|
extern void gql_time_set(gqlValue value, int64_t t);
|
@@ -73,7 +86,15 @@ extern void gql_uuid_set(gqlValue value, uint64_t hi, uint64_t lo);
|
|
73
86
|
extern int gql_uuid_str_set(agooErr err, gqlValue value, const char *str, int len);
|
74
87
|
extern void gql_null_set(gqlValue value);
|
75
88
|
|
89
|
+
extern const char* gql_string_get(gqlValue value);
|
90
|
+
|
76
91
|
extern agooText gql_value_json(agooText text, gqlValue value, int indent, int depth);
|
92
|
+
extern agooText gql_value_sdl(agooText text, gqlValue value, int indent, int depth);
|
93
|
+
|
94
|
+
//extern agooText gql_object_to_json(agooText text, gqlValue value, int indent, int depth);
|
95
|
+
extern agooText gql_object_to_sdl(agooText text, gqlValue value, int indent, int depth);
|
96
|
+
|
97
|
+
extern int gql_value_convert(agooErr err, gqlValue value, struct _gqlType *type);
|
77
98
|
|
78
99
|
extern struct _gqlType gql_null_type;
|
79
100
|
extern struct _gqlType gql_int_type;
|
@@ -82,7 +103,8 @@ extern struct _gqlType gql_bool_type;
|
|
82
103
|
extern struct _gqlType gql_float_type;
|
83
104
|
extern struct _gqlType gql_time_type;
|
84
105
|
extern struct _gqlType gql_uuid_type;
|
85
|
-
extern struct _gqlType gql_url_type;
|
86
106
|
extern struct _gqlType gql_string_type;
|
107
|
+
extern struct _gqlType gql_token_type; // used for enum values
|
108
|
+
extern struct _gqlType gql_var_type; // used for variable keys
|
87
109
|
|
88
110
|
#endif // AGOO_GQLVALUE_H
|
data/ext/agoo/graphql.c
CHANGED
@@ -44,11 +44,12 @@ static uint8_t name_chars[256] = "\
|
|
44
44
|
|
45
45
|
static const char spaces[16] = " ";
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
static gqlType subscription_type = NULL;
|
47
|
+
gqlDir gql_directives = NULL;
|
48
|
+
|
50
49
|
static gqlType schema_type = NULL;
|
51
|
-
static
|
50
|
+
static bool inited = false;
|
51
|
+
|
52
|
+
static void gql_frag_destroy(gqlFrag frag);
|
52
53
|
|
53
54
|
static uint64_t
|
54
55
|
calc_hash(const char *name) {
|
@@ -70,89 +71,184 @@ get_bucketp(uint64_t h) {
|
|
70
71
|
return buckets + (BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
|
71
72
|
}
|
72
73
|
|
73
|
-
static
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
74
|
+
static const char*
|
75
|
+
kind_string(gqlKind kind) {
|
76
|
+
switch (kind) {
|
77
|
+
case GQL_UNDEF: return "undefined";
|
78
|
+
case GQL_OBJECT: return "object";
|
79
|
+
case GQL_INPUT: return "input";
|
80
|
+
case GQL_UNION: return "union";
|
81
|
+
case GQL_INTERFACE: return "interface";
|
82
|
+
case GQL_ENUM: return "enum";
|
83
|
+
case GQL_SCALAR: return "scalar";
|
84
|
+
case GQL_LIST: return "list";
|
85
|
+
default: break;
|
86
|
+
}
|
87
|
+
return "unknown";
|
88
|
+
}
|
89
|
+
|
90
|
+
static char*
|
91
|
+
alloc_string(agooErr err, const char *s, size_t len) {
|
92
|
+
char *a = NULL;
|
93
|
+
|
94
|
+
if (NULL != s) {
|
95
|
+
if (0 >= len) {
|
96
|
+
if (NULL == (a = AGOO_STRDUP(s))) {
|
97
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup() failed.");
|
98
|
+
}
|
99
|
+
len = strlen(a);
|
100
|
+
} else {
|
101
|
+
if (NULL == (a = AGOO_STRNDUP(s, len))) {
|
102
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strndup() of length %d failed.", len);
|
101
103
|
}
|
102
|
-
free(type->interfaces);
|
103
|
-
break;
|
104
104
|
}
|
105
|
-
|
106
|
-
|
105
|
+
}
|
106
|
+
return a;
|
107
|
+
}
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
static void
|
110
|
+
free_dir_uses(gqlDirUse uses) {
|
111
|
+
gqlDirUse u;
|
112
|
+
gqlLink link;
|
113
|
+
|
114
|
+
while (NULL != (u = uses)) {
|
115
|
+
uses = u->next;
|
116
|
+
while (NULL != (link = u->args)) {
|
117
|
+
u->args = link->next;
|
118
|
+
gql_link_destroy(link);
|
114
119
|
}
|
115
|
-
|
116
|
-
|
120
|
+
AGOO_FREE(u);
|
121
|
+
}
|
122
|
+
}
|
117
123
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
+
static void
|
125
|
+
arg_destroy(gqlArg a) {
|
126
|
+
AGOO_FREE((char*)a->name);
|
127
|
+
AGOO_FREE((char*)a->desc);
|
128
|
+
if (NULL != a->default_value) {
|
129
|
+
gql_value_destroy(a->default_value);
|
130
|
+
}
|
131
|
+
free_dir_uses(a->dir);
|
132
|
+
|
133
|
+
AGOO_FREE(a);
|
134
|
+
}
|
135
|
+
|
136
|
+
static void
|
137
|
+
field_destroy(gqlField f) {
|
138
|
+
gqlArg a;
|
139
|
+
|
140
|
+
AGOO_FREE((char*)f->name);
|
141
|
+
AGOO_FREE((char*)f->desc);
|
142
|
+
while (NULL != (a = f->args)) {
|
143
|
+
f->args = a->next;
|
144
|
+
arg_destroy(a);
|
145
|
+
}
|
146
|
+
free_dir_uses(f->dir);
|
147
|
+
if (NULL != f->default_value) {
|
148
|
+
gql_value_destroy(f->default_value);
|
149
|
+
}
|
150
|
+
AGOO_FREE(f);
|
151
|
+
}
|
152
|
+
|
153
|
+
static void
|
154
|
+
type_clean(gqlType type) {
|
155
|
+
AGOO_FREE((char*)type->desc);
|
156
|
+
type->desc = NULL;
|
157
|
+
free_dir_uses(type->dir);
|
158
|
+
type->dir = NULL;
|
159
|
+
|
160
|
+
switch (type->kind) {
|
161
|
+
case GQL_OBJECT:
|
162
|
+
case GQL_INTERFACE: {
|
163
|
+
gqlField f;
|
164
|
+
gqlTypeLink link;
|
165
|
+
|
166
|
+
while (NULL != (f = type->fields)) {
|
167
|
+
type->fields = f->next;
|
168
|
+
field_destroy(f);
|
124
169
|
}
|
125
|
-
|
126
|
-
|
170
|
+
while (NULL != (link = type->interfaces)) {
|
171
|
+
type->interfaces = link->next;
|
172
|
+
AGOO_FREE(link);
|
127
173
|
}
|
128
|
-
|
129
|
-
|
174
|
+
break;
|
175
|
+
}
|
176
|
+
case GQL_INPUT: {
|
177
|
+
gqlArg a;
|
178
|
+
|
179
|
+
while (NULL != (a = type->args)) {
|
180
|
+
type->args = a->next;
|
181
|
+
arg_destroy(a);
|
182
|
+
}
|
183
|
+
break;
|
184
|
+
}
|
185
|
+
case GQL_UNION: {
|
186
|
+
gqlTypeLink link;
|
187
|
+
|
188
|
+
while (NULL != (link = type->types)) {
|
189
|
+
type->types = link->next;
|
190
|
+
AGOO_FREE(link);
|
191
|
+
}
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
case GQL_ENUM: {
|
195
|
+
gqlEnumVal ev;
|
196
|
+
|
197
|
+
while (NULL != (ev = type->choices)) {
|
198
|
+
type->choices = ev->next;
|
199
|
+
AGOO_FREE((char*)ev->value);
|
200
|
+
AGOO_FREE((char*)ev->desc);
|
201
|
+
free_dir_uses(ev->dir);
|
202
|
+
AGOO_FREE(ev);
|
203
|
+
}
|
204
|
+
break;
|
205
|
+
}
|
206
|
+
default:
|
207
|
+
break;
|
130
208
|
}
|
131
209
|
}
|
132
210
|
|
133
211
|
static void
|
134
|
-
|
212
|
+
type_destroy(gqlType type) {
|
213
|
+
if (&gql_int_type == type ||
|
214
|
+
&gql_i64_type == type ||
|
215
|
+
&gql_bool_type == type ||
|
216
|
+
&gql_float_type == type ||
|
217
|
+
&gql_time_type == type ||
|
218
|
+
&gql_uuid_type == type ||
|
219
|
+
&gql_token_type == type ||
|
220
|
+
&gql_var_type == type ||
|
221
|
+
&gql_string_type == type) {
|
222
|
+
|
223
|
+
return;
|
224
|
+
}
|
225
|
+
type_clean(type);
|
226
|
+
AGOO_FREE((char*)type->name);
|
227
|
+
AGOO_FREE(type);
|
228
|
+
}
|
229
|
+
|
230
|
+
static void
|
231
|
+
dir_clean(gqlDir dir) {
|
135
232
|
gqlArg a;
|
136
233
|
gqlStrLink link;
|
137
234
|
|
138
|
-
|
139
|
-
free((char*)dir->desc);
|
235
|
+
AGOO_FREE((char*)dir->desc);
|
140
236
|
while (NULL != (a = dir->args)) {
|
141
237
|
dir->args = a->next;
|
142
|
-
|
143
|
-
free((char*)a->type_name);
|
144
|
-
free((char*)a->desc);
|
145
|
-
gql_value_destroy(a->default_value);
|
146
|
-
DEBUG_FREE(mem_graphql_arg, a);
|
147
|
-
free(a);
|
238
|
+
arg_destroy(a);
|
148
239
|
}
|
149
240
|
while (NULL != (link = dir->locs)) {
|
150
241
|
dir->locs = link->next;
|
151
|
-
|
152
|
-
|
242
|
+
AGOO_FREE(link->str);
|
243
|
+
AGOO_FREE(link);
|
153
244
|
}
|
154
|
-
|
155
|
-
|
245
|
+
}
|
246
|
+
|
247
|
+
static void
|
248
|
+
dir_destroy(gqlDir dir) {
|
249
|
+
AGOO_FREE((char*)dir->name);
|
250
|
+
dir_clean(dir);
|
251
|
+
AGOO_FREE(dir);
|
156
252
|
}
|
157
253
|
|
158
254
|
gqlType
|
@@ -174,9 +270,22 @@ gql_type_get(const char *name) {
|
|
174
270
|
return type;
|
175
271
|
}
|
176
272
|
|
273
|
+
void
|
274
|
+
gql_type_iterate(void (*fun)(gqlType type, void *ctx), void *ctx) {
|
275
|
+
Slot *sp = buckets;
|
276
|
+
Slot s;
|
277
|
+
int i;
|
278
|
+
|
279
|
+
for (i = BUCKET_SIZE; 0 < i; i--, sp++) {
|
280
|
+
for (s = *sp; NULL != s; s = s->next) {
|
281
|
+
fun(s->type, ctx);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
177
286
|
gqlDir
|
178
287
|
gql_directive_get(const char *name) {
|
179
|
-
gqlDir dir =
|
288
|
+
gqlDir dir = gql_directives;
|
180
289
|
|
181
290
|
for (; NULL != dir; dir = dir->next) {
|
182
291
|
if (0 == strcmp(name, dir->name)) {
|
@@ -203,10 +312,9 @@ gql_type_set(agooErr err, gqlType type) {
|
|
203
312
|
return AGOO_ERR_OK;
|
204
313
|
}
|
205
314
|
}
|
206
|
-
if (NULL == (s = (Slot)
|
207
|
-
return agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
315
|
+
if (NULL == (s = (Slot)AGOO_MALLOC(sizeof(struct _slot)))) {
|
316
|
+
return agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL type.");
|
208
317
|
}
|
209
|
-
DEBUG_ALLOC(mem_graphql_slot, s);
|
210
318
|
s->hash = h;
|
211
319
|
s->type = type;
|
212
320
|
s->next = *bucket;
|
@@ -231,8 +339,7 @@ type_remove(gqlType type) {
|
|
231
339
|
} else {
|
232
340
|
prev->next = s->next;
|
233
341
|
}
|
234
|
-
|
235
|
-
free(s);
|
342
|
+
AGOO_FREE(s);
|
236
343
|
|
237
344
|
break;
|
238
345
|
}
|
@@ -243,24 +350,32 @@ type_remove(gqlType type) {
|
|
243
350
|
|
244
351
|
int
|
245
352
|
gql_init(agooErr err) {
|
246
|
-
|
353
|
+
gqlType query_type;
|
354
|
+
gqlType mutation_type;
|
355
|
+
gqlType subscription_type;
|
247
356
|
|
357
|
+
if (inited) {
|
358
|
+
return AGOO_ERR_OK;
|
359
|
+
}
|
360
|
+
memset(buckets, 0, sizeof(buckets));
|
248
361
|
if (AGOO_ERR_OK != gql_value_init(err) ||
|
249
362
|
AGOO_ERR_OK != gql_intro_init(err)) {
|
250
363
|
|
251
364
|
return err->code;
|
252
365
|
}
|
253
|
-
if (
|
254
|
-
NULL == (
|
255
|
-
NULL == (
|
256
|
-
NULL == (
|
257
|
-
|
258
|
-
NULL == gql_type_field(err, schema_type, "query", query_type, "Root level query.",
|
259
|
-
NULL == gql_type_field(err, schema_type, "mutation", mutation_type, "Root level mutation.",
|
260
|
-
NULL == gql_type_field(err, schema_type, "subscription", subscription_type, "Root level subscription.",
|
366
|
+
if (NULL == (query_type = gql_type_create(err, "Query", "The GraphQL root Query.", 0, NULL)) ||
|
367
|
+
NULL == (mutation_type = gql_type_create(err, "Mutation", "The GraphQL root Mutation.", 0, NULL)) ||
|
368
|
+
NULL == (subscription_type = gql_type_create(err, "Subscription", "The GraphQL root Subscription.", 0, NULL)) ||
|
369
|
+
NULL == (schema_type = gql_type_create(err, "schema", "The GraphQL root Object.", 0, NULL)) ||
|
370
|
+
|
371
|
+
NULL == gql_type_field(err, schema_type, "query", query_type, NULL, "Root level query.", 0, false) ||
|
372
|
+
NULL == gql_type_field(err, schema_type, "mutation", mutation_type, NULL, "Root level mutation.", 0, false) ||
|
373
|
+
NULL == gql_type_field(err, schema_type, "subscription", subscription_type, NULL, "Root level subscription.", 0, false)) {
|
261
374
|
|
262
375
|
return err->code;
|
263
376
|
}
|
377
|
+
inited = true;
|
378
|
+
|
264
379
|
return AGOO_ERR_OK;
|
265
380
|
}
|
266
381
|
|
@@ -271,63 +386,69 @@ gql_destroy() {
|
|
271
386
|
Slot n;
|
272
387
|
int i;
|
273
388
|
gqlDir dir;
|
274
|
-
|
275
|
-
for (i = BUCKET_SIZE; 0 < i; i--, sp++) {
|
276
|
-
Slot *b = sp;
|
277
389
|
|
390
|
+
for (i = BUCKET_SIZE; 0 < i; i--, sp++) {
|
391
|
+
s = *sp;
|
392
|
+
|
278
393
|
*sp = NULL;
|
279
|
-
for (
|
394
|
+
for (; NULL != s; s = n) {
|
280
395
|
n = s->next;
|
281
|
-
|
282
|
-
|
283
|
-
free(s);
|
396
|
+
type_destroy(s->type);
|
397
|
+
AGOO_FREE(s);
|
284
398
|
}
|
285
|
-
*sp = NULL;
|
286
399
|
}
|
287
|
-
while (NULL != (dir =
|
288
|
-
|
400
|
+
while (NULL != (dir = gql_directives)) {
|
401
|
+
gql_directives = dir->next;
|
289
402
|
dir_destroy(dir);
|
290
403
|
}
|
404
|
+
inited = false;
|
291
405
|
}
|
292
406
|
|
293
407
|
static gqlType
|
294
|
-
type_create(agooErr err, const char *name, const char *desc,
|
295
|
-
gqlType type = (
|
408
|
+
type_create(agooErr err, gqlKind kind, const char *name, const char *desc, size_t dlen) {
|
409
|
+
gqlType type = gql_type_get(name);
|
296
410
|
|
297
411
|
if (NULL == type) {
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
if (NULL ==
|
303
|
-
type
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
type->desc = strndup(desc, dlen);
|
309
|
-
}
|
310
|
-
if (NULL == type->desc) {
|
311
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup or strndup of length %d failed.", dlen);
|
312
|
-
return NULL;
|
313
|
-
}
|
412
|
+
if (NULL == (type = (gqlType)AGOO_MALLOC(sizeof(struct _gqlType)))) {
|
413
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL Type.");
|
414
|
+
return NULL;
|
415
|
+
}
|
416
|
+
if (NULL == (type->name = AGOO_STRDUP(name))) {
|
417
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup of type name failed. %s:%d", __FILE__, __LINE__);
|
418
|
+
return NULL;
|
419
|
+
}
|
420
|
+
if (NULL == (type->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
421
|
+
return NULL;
|
314
422
|
}
|
315
|
-
type->locked = locked;
|
316
|
-
type->core = false;
|
317
423
|
type->dir = NULL;
|
424
|
+
type->kind = kind;
|
425
|
+
type->scalar_kind = GQL_SCALAR_UNDEF;
|
426
|
+
type->core = false;
|
318
427
|
|
319
428
|
if (AGOO_ERR_OK != gql_type_set(err, type)) {
|
320
429
|
gql_type_destroy(type);
|
321
430
|
type = NULL;
|
322
431
|
}
|
432
|
+
} else if (GQL_UNDEF == type->kind) {
|
433
|
+
if (NULL == (type->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
434
|
+
return NULL;
|
435
|
+
}
|
436
|
+
type->kind = kind;
|
437
|
+
} else if (type->core) {
|
438
|
+
agoo_err_set(err, AGOO_ERR_LOCK, "%d can not be modified.", name);
|
439
|
+
return NULL;
|
440
|
+
} else if (kind == type->kind) { // looks like it is being modified so remove all the old stuff
|
441
|
+
type_clean(type);
|
442
|
+
} else {
|
443
|
+
agoo_err_set(err, AGOO_ERR_LOCK, "%d already exists as a %s.", name, kind_string(type->kind));
|
444
|
+
return NULL;
|
323
445
|
}
|
324
446
|
return type;
|
325
447
|
}
|
326
448
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
return text;
|
449
|
+
static gqlType
|
450
|
+
type_undef_create(agooErr err, const char *name) {
|
451
|
+
return type_create(err, GQL_UNDEF, name, NULL, 0);
|
331
452
|
}
|
332
453
|
|
333
454
|
agooText
|
@@ -337,70 +458,76 @@ gql_object_to_graphql(agooText text, gqlValue value, int indent, int depth) {
|
|
337
458
|
}
|
338
459
|
|
339
460
|
gqlType
|
340
|
-
|
341
|
-
gqlType type =
|
342
|
-
|
343
|
-
if (NULL !=
|
344
|
-
type
|
345
|
-
type->to_json = gql_object_to_json;
|
346
|
-
type->fields = NULL;
|
347
|
-
type->interfaces = NULL;
|
348
|
-
if (NULL != interfaces) {
|
349
|
-
gqlType *tp = interfaces;
|
350
|
-
gqlType *np;
|
351
|
-
int cnt = 0;
|
461
|
+
gql_assure_type(agooErr err, const char *name) {
|
462
|
+
gqlType type = NULL;
|
463
|
+
|
464
|
+
if (NULL != name) {
|
465
|
+
type = gql_type_get(name);
|
352
466
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
if (0 < cnt) {
|
357
|
-
if (NULL == (type->interfaces = (gqlType*)malloc(sizeof(gqlType) * (cnt + 1)))) {
|
358
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocation memory for a GraphQL type interfaces.");
|
359
|
-
free(type);
|
360
|
-
return NULL;
|
361
|
-
}
|
362
|
-
for (np = type->interfaces, tp = interfaces; NULL != *tp; np++, tp++) {
|
363
|
-
*np = *tp;
|
364
|
-
}
|
365
|
-
*np = NULL;
|
467
|
+
if (NULL == type) {
|
468
|
+
if (NULL == (type = type_undef_create(err, name))) {
|
469
|
+
return NULL;
|
366
470
|
}
|
367
471
|
}
|
368
472
|
}
|
369
473
|
return type;
|
370
474
|
}
|
371
475
|
|
476
|
+
static gqlDir
|
477
|
+
assure_directive(agooErr err, const char *name) {
|
478
|
+
gqlDir dir = gql_directive_get(name);
|
479
|
+
|
480
|
+
if (NULL == dir) {
|
481
|
+
if (NULL == (dir = (gqlDir)AGOO_MALLOC(sizeof(struct _gqlDir)))) {
|
482
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL directive.");
|
483
|
+
return NULL;
|
484
|
+
}
|
485
|
+
dir->next = gql_directives;
|
486
|
+
gql_directives = dir;
|
487
|
+
dir->name = AGOO_STRDUP(name);
|
488
|
+
dir->args = NULL;
|
489
|
+
dir->locs = NULL;
|
490
|
+
dir->defined = false;
|
491
|
+
dir->desc = NULL;
|
492
|
+
}
|
493
|
+
return dir;
|
494
|
+
}
|
495
|
+
|
496
|
+
gqlType
|
497
|
+
gql_type_create(agooErr err, const char *name, const char *desc, size_t dlen, gqlTypeLink interfaces) {
|
498
|
+
gqlType type = type_create(err, GQL_OBJECT, name, desc, dlen);
|
499
|
+
|
500
|
+
if (NULL != type) {
|
501
|
+
type->fields = NULL;
|
502
|
+
type->interfaces = interfaces;
|
503
|
+
}
|
504
|
+
return type;
|
505
|
+
}
|
506
|
+
|
372
507
|
gqlField
|
373
|
-
gql_type_field(agooErr
|
374
|
-
gqlType
|
375
|
-
const char
|
376
|
-
gqlType
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
bool
|
381
|
-
|
382
|
-
gqlField f = (gqlField)malloc(sizeof(struct _gqlField));
|
508
|
+
gql_type_field(agooErr err,
|
509
|
+
gqlType type,
|
510
|
+
const char *name,
|
511
|
+
gqlType return_type,
|
512
|
+
gqlValue default_value,
|
513
|
+
const char *desc,
|
514
|
+
size_t dlen,
|
515
|
+
bool required) {
|
516
|
+
gqlField f = (gqlField)AGOO_MALLOC(sizeof(struct _gqlField));
|
383
517
|
|
384
518
|
if (NULL == f) {
|
385
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
519
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL field.");
|
386
520
|
} else {
|
387
|
-
DEBUG_ALLOC(mem_graphql_field, f);
|
388
521
|
f->next = NULL;
|
389
|
-
f->name =
|
522
|
+
f->name = AGOO_STRDUP(name);
|
390
523
|
f->type = return_type;
|
391
|
-
if (NULL == desc) {
|
392
|
-
|
393
|
-
} else {
|
394
|
-
f->desc = strdup(desc);
|
524
|
+
if (NULL == (f->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
525
|
+
return NULL;
|
395
526
|
}
|
396
|
-
f->reason = NULL;
|
397
527
|
f->args = NULL;
|
398
528
|
f->dir = NULL;
|
399
|
-
f->
|
529
|
+
f->default_value = default_value;
|
400
530
|
f->required = required;
|
401
|
-
f->list = list;
|
402
|
-
f->not_empty = not_empty;
|
403
|
-
f->deprecated = false;
|
404
531
|
if (NULL == type->fields) {
|
405
532
|
type->fields = f;
|
406
533
|
} else {
|
@@ -420,21 +547,19 @@ gql_field_arg(agooErr err,
|
|
420
547
|
const char *name,
|
421
548
|
gqlType type,
|
422
549
|
const char *desc,
|
550
|
+
size_t dlen,
|
423
551
|
struct _gqlValue *def_value,
|
424
552
|
bool required) {
|
425
|
-
gqlArg a = (gqlArg)
|
553
|
+
gqlArg a = (gqlArg)AGOO_MALLOC(sizeof(struct _gqlArg));
|
426
554
|
|
427
555
|
if (NULL == a) {
|
428
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
556
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL field argument.");
|
429
557
|
} else {
|
430
|
-
DEBUG_ALLOC(mem_graphql_arg, a);
|
431
558
|
a->next = NULL;
|
432
|
-
a->name =
|
559
|
+
a->name = AGOO_STRDUP(name);
|
433
560
|
a->type = type;
|
434
|
-
if (NULL == desc) {
|
435
|
-
|
436
|
-
} else {
|
437
|
-
a->desc = strdup(desc);
|
561
|
+
if (NULL == (a->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
562
|
+
return NULL;
|
438
563
|
}
|
439
564
|
a->default_value = def_value;
|
440
565
|
a->dir = NULL;
|
@@ -452,37 +577,24 @@ gql_field_arg(agooErr err,
|
|
452
577
|
return a;
|
453
578
|
}
|
454
579
|
|
455
|
-
agooText
|
456
|
-
gql_union_to_json(agooText text, gqlValue value, int indent, int depth) {
|
457
|
-
// TBD
|
458
|
-
return text;
|
459
|
-
}
|
460
|
-
|
461
580
|
gqlType
|
462
|
-
gql_union_create(agooErr err, const char *name, const char *desc,
|
463
|
-
gqlType type = type_create(err, name, desc, dlen
|
581
|
+
gql_union_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
582
|
+
gqlType type = type_create(err, GQL_UNION, name, desc, dlen);
|
464
583
|
|
465
584
|
if (NULL != type) {
|
466
|
-
type->kind = GQL_UNION;
|
467
|
-
type->to_json = gql_union_to_json;
|
468
585
|
type->types = NULL;
|
469
586
|
}
|
470
587
|
return type;
|
471
588
|
}
|
472
589
|
|
473
590
|
int
|
474
|
-
gql_union_add(agooErr err, gqlType type,
|
475
|
-
gqlTypeLink link = (gqlTypeLink)
|
591
|
+
gql_union_add(agooErr err, gqlType type, gqlType member) {
|
592
|
+
gqlTypeLink link = (gqlTypeLink)AGOO_MALLOC(sizeof(struct _gqlTypeLink));
|
476
593
|
|
477
594
|
if (NULL == link) {
|
478
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
479
|
-
}
|
480
|
-
if (0 >= len) {
|
481
|
-
len = (int)strlen(name);
|
482
|
-
}
|
483
|
-
if (NULL == (link->name = strndup(name, len))) {
|
484
|
-
return agoo_err_set(err, AGOO_ERR_MEMORY, "strndup of length %d failed.", len);
|
595
|
+
return agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL Union value.");
|
485
596
|
}
|
597
|
+
link->type = member;
|
486
598
|
if (NULL == type->types) {
|
487
599
|
link->next = type->types;
|
488
600
|
type->types = link;
|
@@ -497,175 +609,122 @@ gql_union_add(agooErr err, gqlType type, const char *name, int len) {
|
|
497
609
|
return AGOO_ERR_OK;
|
498
610
|
}
|
499
611
|
|
500
|
-
agooText
|
501
|
-
gql_enum_to_json(agooText text, gqlValue value, int indent, int depth) {
|
502
|
-
// TBD
|
503
|
-
return text;
|
504
|
-
}
|
505
|
-
|
506
612
|
gqlType
|
507
|
-
gql_enum_create(agooErr err, const char *name, const char *desc,
|
508
|
-
gqlType type = type_create(err, name, desc, dlen
|
613
|
+
gql_enum_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
614
|
+
gqlType type = type_create(err, GQL_ENUM, name, desc, dlen);
|
509
615
|
|
510
616
|
if (NULL != type) {
|
511
|
-
type->kind = GQL_ENUM;
|
512
|
-
type->to_json = gql_enum_to_json;
|
513
617
|
type->choices = NULL;
|
514
618
|
}
|
515
619
|
return type;
|
516
620
|
}
|
517
621
|
|
518
|
-
|
519
|
-
|
520
|
-
|
622
|
+
gqlEnumVal
|
623
|
+
gql_enum_append(agooErr err, gqlType type, const char *value, size_t len, const char *desc, size_t dlen) {
|
624
|
+
gqlEnumVal ev = (gqlEnumVal)AGOO_MALLOC(sizeof(struct _gqlEnumVal));
|
521
625
|
|
522
|
-
if (NULL ==
|
523
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
626
|
+
if (NULL == ev) {
|
627
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL Enum value.");
|
628
|
+
return NULL;
|
524
629
|
}
|
525
630
|
if (0 >= len) {
|
526
|
-
len =
|
527
|
-
}
|
528
|
-
link->next = type->choices;
|
529
|
-
type->choices = link;
|
530
|
-
if (NULL == (link->str = strndup(value, len))) {
|
531
|
-
return agoo_err_set(err, AGOO_ERR_MEMORY, "strdup or strndup of length %d failed.", len);
|
532
|
-
}
|
533
|
-
return AGOO_ERR_OK;
|
534
|
-
}
|
535
|
-
|
536
|
-
int
|
537
|
-
gql_enum_append(agooErr err, gqlType type, const char *value, int len) {
|
538
|
-
gqlStrLink link = (gqlStrLink)malloc(sizeof(gqlStrLink));
|
539
|
-
|
540
|
-
if (NULL == link) {
|
541
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocation memory for a GraphQL Enum value.");
|
631
|
+
len = strlen(value);
|
542
632
|
}
|
543
|
-
if (
|
544
|
-
len
|
633
|
+
if (NULL == (ev->value = AGOO_STRNDUP(value, len))) {
|
634
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strndup of length %d failed. %s:%d", len, __FILE__, __LINE__);
|
635
|
+
return NULL;
|
545
636
|
}
|
546
|
-
|
547
|
-
|
637
|
+
ev->dir = NULL;
|
638
|
+
if (NULL == (ev->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
639
|
+
return NULL;
|
548
640
|
}
|
549
641
|
if (NULL == type->choices) {
|
550
|
-
|
551
|
-
type->choices =
|
642
|
+
ev->next = type->choices;
|
643
|
+
type->choices = ev;
|
552
644
|
} else {
|
553
|
-
|
645
|
+
gqlEnumVal last = type->choices;
|
554
646
|
|
555
647
|
for (; NULL != last->next; last = last->next) {
|
556
648
|
}
|
557
|
-
|
558
|
-
last->next =
|
559
|
-
}
|
560
|
-
return AGOO_ERR_OK;
|
561
|
-
}
|
562
|
-
|
563
|
-
static agooText
|
564
|
-
fragment_to_json(agooText text, gqlValue value, int indent, int depth) {
|
565
|
-
// TBD
|
566
|
-
return text;
|
567
|
-
}
|
568
|
-
|
569
|
-
gqlType
|
570
|
-
gql_fragment_create(agooErr err, const char *name, const char *desc, int dlen, bool locked, gqlType on) {
|
571
|
-
gqlType type = type_create(err, name, desc, dlen, locked);
|
572
|
-
|
573
|
-
if (NULL != type) {
|
574
|
-
type->kind = GQL_FRAG;
|
575
|
-
type->to_json = fragment_to_json;
|
576
|
-
type->fields = NULL;
|
577
|
-
type->on = on;
|
649
|
+
ev->next = NULL;
|
650
|
+
last->next = ev;
|
578
651
|
}
|
579
|
-
return
|
580
|
-
}
|
581
|
-
|
582
|
-
static agooText
|
583
|
-
input_to_json(agooText text, gqlValue value, int indent, int depth) {
|
584
|
-
// TBD
|
585
|
-
return text;
|
652
|
+
return ev;
|
586
653
|
}
|
587
654
|
|
588
655
|
gqlType
|
589
|
-
gql_input_create(agooErr err, const char *name, const char *desc,
|
590
|
-
gqlType type = type_create(err, name, desc, dlen
|
656
|
+
gql_input_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
657
|
+
gqlType type = type_create(err, GQL_INPUT, name, desc, dlen);
|
591
658
|
|
592
659
|
if (NULL != type) {
|
593
|
-
type->
|
594
|
-
type->to_json = input_to_json;
|
595
|
-
type->fields = NULL;
|
660
|
+
type->args = NULL;
|
596
661
|
}
|
597
662
|
return type;
|
598
663
|
}
|
599
664
|
|
600
|
-
static agooText
|
601
|
-
interface_to_json(agooText text, gqlValue value, int indent, int depth) {
|
602
|
-
// TBD
|
603
|
-
return text;
|
604
|
-
}
|
605
|
-
|
606
665
|
gqlType
|
607
|
-
gql_interface_create(agooErr err, const char *name, const char *desc,
|
608
|
-
gqlType type = type_create(err, name, desc, dlen
|
666
|
+
gql_interface_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
667
|
+
gqlType type = type_create(err, GQL_INTERFACE, name, desc, dlen);
|
609
668
|
|
610
669
|
if (NULL != type) {
|
611
|
-
type->kind = GQL_INTERFACE;
|
612
|
-
type->to_json = interface_to_json;
|
613
670
|
type->fields = NULL;
|
671
|
+
type->interfaces = NULL;
|
614
672
|
}
|
615
673
|
return type;
|
616
674
|
}
|
617
675
|
|
676
|
+
// TBD this is not correct. Is it used?
|
618
677
|
static agooText
|
619
|
-
|
620
|
-
|
621
|
-
text = agoo_text_append(text, "null", 4);
|
622
|
-
} else {
|
623
|
-
text = agoo_text_append(text, "\"", 1);
|
624
|
-
text = agoo_text_append(text, value->str, -1);
|
625
|
-
text = agoo_text_append(text, "\"", 1);
|
626
|
-
}
|
678
|
+
scalar_to_text(agooText text, gqlValue value, int indent, int depth) {
|
679
|
+
printf("********** scalar_to_text\n");
|
627
680
|
return text;
|
628
681
|
}
|
629
682
|
|
630
683
|
// Create a scalar type that will be represented as a string.
|
631
684
|
gqlType
|
632
|
-
gql_scalar_create(agooErr err, const char *name, const char *desc,
|
633
|
-
gqlType type = type_create(err, name, desc, dlen
|
685
|
+
gql_scalar_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
686
|
+
gqlType type = type_create(err, GQL_SCALAR, name, desc, dlen);
|
634
687
|
|
635
688
|
if (NULL != type) {
|
636
|
-
type->
|
637
|
-
type->
|
638
|
-
type->coerce = NULL;
|
689
|
+
type->to_json = scalar_to_text;
|
690
|
+
type->to_sdl = scalar_to_text;
|
639
691
|
type->destroy = NULL;
|
640
692
|
}
|
641
693
|
return type;
|
642
694
|
}
|
643
695
|
|
644
696
|
gqlDir
|
645
|
-
gql_directive_create(agooErr err, const char *name, const char *desc,
|
646
|
-
gqlDir dir;
|
647
|
-
|
648
|
-
if (NULL
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
directives = dir;
|
655
|
-
dir->name = strdup(name);
|
656
|
-
dir->args = NULL;
|
657
|
-
dir->locs = NULL;
|
658
|
-
dir->locked = locked;
|
659
|
-
if (NULL == desc) {
|
660
|
-
dir->desc = NULL;
|
661
|
-
} else {
|
662
|
-
if (0 >= dlen) {
|
663
|
-
dir->desc = strdup(desc);
|
697
|
+
gql_directive_create(agooErr err, const char *name, const char *desc, size_t dlen) {
|
698
|
+
gqlDir dir = gql_directive_get(name);
|
699
|
+
|
700
|
+
if (NULL != dir) {
|
701
|
+
if (!dir->defined) {
|
702
|
+
dir->defined = true;
|
703
|
+
if (NULL == (dir->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
704
|
+
return NULL;
|
705
|
+
}
|
664
706
|
} else {
|
665
|
-
dir
|
707
|
+
dir_clean(dir);
|
708
|
+
dir->args = NULL;
|
709
|
+
dir->locs = NULL;
|
710
|
+
dir->defined = true;
|
711
|
+
if (NULL == (dir->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
712
|
+
return NULL;
|
713
|
+
}
|
666
714
|
}
|
667
|
-
|
668
|
-
|
715
|
+
} else {
|
716
|
+
if (NULL == (dir = (gqlDir)AGOO_MALLOC(sizeof(struct _gqlDir)))) {
|
717
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL directive.");
|
718
|
+
return NULL;
|
719
|
+
}
|
720
|
+
dir->next = gql_directives;
|
721
|
+
gql_directives = dir;
|
722
|
+
dir->name = AGOO_STRDUP(name);
|
723
|
+
dir->args = NULL;
|
724
|
+
dir->locs = NULL;
|
725
|
+
dir->defined = true;
|
726
|
+
dir->core = false;
|
727
|
+
if (NULL == (dir->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
669
728
|
return NULL;
|
670
729
|
}
|
671
730
|
}
|
@@ -676,31 +735,21 @@ gqlArg
|
|
676
735
|
gql_dir_arg(agooErr err,
|
677
736
|
gqlDir dir,
|
678
737
|
const char *name,
|
679
|
-
|
738
|
+
gqlType type,
|
680
739
|
const char *desc,
|
681
|
-
|
740
|
+
size_t dlen,
|
682
741
|
struct _gqlValue *def_value,
|
683
742
|
bool required) {
|
684
743
|
|
685
|
-
gqlArg a = (gqlArg)
|
744
|
+
gqlArg a = (gqlArg)AGOO_MALLOC(sizeof(struct _gqlArg));
|
686
745
|
|
687
746
|
if (NULL == a) {
|
688
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
747
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL directive argument.");
|
689
748
|
} else {
|
690
|
-
DEBUG_ALLOC(mem_graphql_arg, a);
|
691
749
|
a->next = NULL;
|
692
|
-
a->name =
|
693
|
-
a->
|
694
|
-
a->
|
695
|
-
if (NULL == desc) {
|
696
|
-
a->desc = NULL;
|
697
|
-
} else if (0 < dlen) {
|
698
|
-
a->desc = strdup(desc);
|
699
|
-
} else {
|
700
|
-
a->desc = strndup(desc, dlen);
|
701
|
-
}
|
702
|
-
if (NULL == a->desc) {
|
703
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup or strndup of length %d failed.", dlen);
|
750
|
+
a->name = AGOO_STRDUP(name);
|
751
|
+
a->type = type;
|
752
|
+
if (NULL == (a->desc = alloc_string(err, desc, dlen)) && AGOO_ERR_OK != err->code) {
|
704
753
|
return NULL;
|
705
754
|
}
|
706
755
|
a->default_value = def_value;
|
@@ -721,11 +770,11 @@ gql_dir_arg(agooErr err,
|
|
721
770
|
|
722
771
|
int
|
723
772
|
gql_directive_on(agooErr err, gqlDir d, const char *on, int len) {
|
724
|
-
gqlStrLink link = (gqlStrLink)
|
773
|
+
gqlStrLink link = (gqlStrLink)AGOO_MALLOC(sizeof(struct _gqlStrLink));
|
725
774
|
gqlStrLink loc;
|
726
775
|
|
727
776
|
if (NULL == link) {
|
728
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to
|
777
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a GraphQL directive location.");
|
729
778
|
}
|
730
779
|
if (0 >= len) {
|
731
780
|
len = (int)strlen(on);
|
@@ -739,12 +788,31 @@ gql_directive_on(agooErr err, gqlDir d, const char *on, int len) {
|
|
739
788
|
}
|
740
789
|
loc->next = link;
|
741
790
|
}
|
742
|
-
if (NULL == (link->str =
|
743
|
-
return agoo_err_set(err, AGOO_ERR_MEMORY, "
|
791
|
+
if (NULL == (link->str = AGOO_STRNDUP(on, len))) {
|
792
|
+
return agoo_err_set(err, AGOO_ERR_MEMORY, "strndup of length %d failed. %s:%d", len, __FILE__, __LINE__);
|
744
793
|
}
|
745
794
|
return AGOO_ERR_OK;
|
746
795
|
}
|
747
796
|
|
797
|
+
gqlType
|
798
|
+
gql_assure_list(agooErr err, gqlType base, bool not_empty) {
|
799
|
+
char name[256];
|
800
|
+
gqlType type;
|
801
|
+
|
802
|
+
if ((int)sizeof(name) <= snprintf(name, sizeof(name), "[%s%s]", base->name, not_empty ? "!" : "")) {
|
803
|
+
agoo_err_set(err, AGOO_ERR_ARG, "Name too long");
|
804
|
+
return NULL;
|
805
|
+
}
|
806
|
+
if (NULL == (type = gql_type_get(name))) {
|
807
|
+
if (NULL == (type = type_create(err, GQL_LIST, name, NULL, 0))) {
|
808
|
+
return NULL;
|
809
|
+
}
|
810
|
+
type->base = base;
|
811
|
+
type->not_empty = not_empty;
|
812
|
+
}
|
813
|
+
return type;
|
814
|
+
}
|
815
|
+
|
748
816
|
void
|
749
817
|
gql_type_destroy(gqlType type) {
|
750
818
|
type_destroy(type);
|
@@ -825,15 +893,14 @@ arg_sdl(agooText text, gqlArg a, bool with_desc, bool last) {
|
|
825
893
|
text = desc_sdl(text, a->desc, 4);
|
826
894
|
}
|
827
895
|
text = agoo_text_append(text, a->name, -1);
|
896
|
+
text = agoo_text_append(text, ": ", 2);
|
897
|
+
text = agoo_text_append(text, a->type->name, -1);
|
828
898
|
if (a->required) {
|
829
|
-
text = agoo_text_append(text, "
|
830
|
-
} else {
|
831
|
-
text = agoo_text_append(text, ": ", 2);
|
899
|
+
text = agoo_text_append(text, "!", 1);
|
832
900
|
}
|
833
|
-
text = agoo_text_append(text, a->type_name, -1);
|
834
901
|
if (NULL != a->default_value) {
|
835
902
|
text = agoo_text_append(text, " = ", 3);
|
836
|
-
text =
|
903
|
+
text = gql_value_sdl(text, a->default_value, 0, 0);
|
837
904
|
}
|
838
905
|
if (!last) {
|
839
906
|
text = agoo_text_append(text, ", ", 2);
|
@@ -841,6 +908,26 @@ arg_sdl(agooText text, gqlArg a, bool with_desc, bool last) {
|
|
841
908
|
return text;
|
842
909
|
}
|
843
910
|
|
911
|
+
static agooText
|
912
|
+
append_dir_use(agooText text, gqlDirUse use) {
|
913
|
+
for (; NULL != use; use = use->next) {
|
914
|
+
text = agoo_text_append(text, " @", 2);
|
915
|
+
text = agoo_text_append(text, use->dir->name, -1);
|
916
|
+
if (NULL != use->args) {
|
917
|
+
gqlLink link;
|
918
|
+
|
919
|
+
text = agoo_text_append(text, "(", 1);
|
920
|
+
for (link = use->args; NULL != link; link = link->next) {
|
921
|
+
text = agoo_text_append(text, link->key, -1);
|
922
|
+
text = agoo_text_append(text, ": ", 2);
|
923
|
+
text = gql_value_sdl(text, link->value, 0, 0);
|
924
|
+
}
|
925
|
+
text = agoo_text_append(text, ")", 1);
|
926
|
+
}
|
927
|
+
}
|
928
|
+
return text;
|
929
|
+
}
|
930
|
+
|
844
931
|
static agooText
|
845
932
|
field_sdl(agooText text, gqlField f, bool with_desc) {
|
846
933
|
if (with_desc) {
|
@@ -858,19 +945,15 @@ field_sdl(agooText text, gqlField f, bool with_desc) {
|
|
858
945
|
text = agoo_text_append(text, ")", 1);
|
859
946
|
}
|
860
947
|
text = agoo_text_append(text, ": ", 2);
|
861
|
-
|
862
|
-
text = agoo_text_append(text, "[", 1);
|
863
|
-
text = agoo_text_append(text, f->type->name, -1);
|
864
|
-
if (f->not_empty) {
|
865
|
-
text = agoo_text_append(text, "!", 1);
|
866
|
-
}
|
867
|
-
text = agoo_text_append(text, "]", 1);
|
868
|
-
} else {
|
869
|
-
text = agoo_text_append(text, f->type->name, -1);
|
870
|
-
}
|
948
|
+
text = agoo_text_append(text, f->type->name, -1);
|
871
949
|
if (f->required) {
|
872
950
|
text = agoo_text_append(text, "!", 1);
|
873
951
|
}
|
952
|
+
if (NULL != f->default_value) {
|
953
|
+
text = agoo_text_append(text, " = ", 3);
|
954
|
+
text = gql_value_sdl(text, f->default_value, 0, 0);
|
955
|
+
}
|
956
|
+
text = append_dir_use(text, f->dir);
|
874
957
|
text = agoo_text_append(text, "\n", 1);
|
875
958
|
|
876
959
|
return text;
|
@@ -889,16 +972,17 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
889
972
|
text = agoo_text_append(text, "type ", 5);
|
890
973
|
text = agoo_text_append(text, type->name, -1);
|
891
974
|
if (NULL != type->interfaces) {
|
892
|
-
|
975
|
+
gqlTypeLink tp = type->interfaces;
|
893
976
|
|
894
977
|
text = agoo_text_append(text, " implements ", 12);
|
895
|
-
for (; NULL !=
|
896
|
-
text = agoo_text_append(text,
|
897
|
-
if (NULL !=
|
898
|
-
text = agoo_text_append(text, "
|
978
|
+
for (; NULL != tp; tp = tp->next) {
|
979
|
+
text = agoo_text_append(text, tp->type->name, -1);
|
980
|
+
if (NULL != tp->next) {
|
981
|
+
text = agoo_text_append(text, " & ", 3);
|
899
982
|
}
|
900
983
|
}
|
901
984
|
}
|
985
|
+
text = append_dir_use(text, type->dir);
|
902
986
|
text = agoo_text_append(text, " {\n", 3);
|
903
987
|
for (f = type->fields; NULL != f; f = f->next) {
|
904
988
|
text = field_sdl(text, f, with_desc);
|
@@ -911,9 +995,10 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
911
995
|
|
912
996
|
text = agoo_text_append(text, "union ", 6);
|
913
997
|
text = agoo_text_append(text, type->name, -1);
|
998
|
+
text = append_dir_use(text, type->dir);
|
914
999
|
text = agoo_text_append(text, " = ", 3);
|
915
1000
|
for (link = type->types; NULL != link; link = link->next) {
|
916
|
-
text = agoo_text_append(text, link->name, -1);
|
1001
|
+
text = agoo_text_append(text, link->type->name, -1);
|
917
1002
|
if (NULL != link->next) {
|
918
1003
|
text = agoo_text_append(text, " | ", 3);
|
919
1004
|
}
|
@@ -921,14 +1006,19 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
921
1006
|
break;
|
922
1007
|
}
|
923
1008
|
case GQL_ENUM: {
|
924
|
-
|
1009
|
+
gqlEnumVal ev;
|
925
1010
|
|
926
1011
|
text = agoo_text_append(text, "enum ", 5);
|
927
1012
|
text = agoo_text_append(text, type->name, -1);
|
1013
|
+
text = append_dir_use(text, type->dir);
|
928
1014
|
text = agoo_text_append(text, " {\n", 3);
|
929
|
-
for (
|
1015
|
+
for (ev = type->choices; NULL != ev; ev = ev->next) {
|
930
1016
|
text = agoo_text_append(text, " ", 2);
|
931
|
-
|
1017
|
+
if (with_desc) {
|
1018
|
+
text = desc_sdl(text, ev->desc, 2);
|
1019
|
+
}
|
1020
|
+
text = agoo_text_append(text, ev->value, -1);
|
1021
|
+
text = append_dir_use(text, ev->dir);
|
932
1022
|
text = agoo_text_append(text, "\n", 1);
|
933
1023
|
}
|
934
1024
|
text = agoo_text_append(text, "}\n", 2);
|
@@ -937,6 +1027,7 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
937
1027
|
case GQL_SCALAR:
|
938
1028
|
text = agoo_text_append(text, "scalar ", 7);
|
939
1029
|
text = agoo_text_append(text, type->name, -1);
|
1030
|
+
text = append_dir_use(text, type->dir);
|
940
1031
|
text = agoo_text_append(text, "\n", 1);
|
941
1032
|
break;
|
942
1033
|
case GQL_INTERFACE: {
|
@@ -944,6 +1035,7 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
944
1035
|
|
945
1036
|
text = agoo_text_append(text, "interface ", 10);
|
946
1037
|
text = agoo_text_append(text, type->name, -1);
|
1038
|
+
text = append_dir_use(text, type->dir);
|
947
1039
|
text = agoo_text_append(text, " {\n", 3);
|
948
1040
|
|
949
1041
|
for (f = type->fields; NULL != f; f = f->next) {
|
@@ -953,13 +1045,14 @@ gql_type_sdl(agooText text, gqlType type, bool with_desc) {
|
|
953
1045
|
break;
|
954
1046
|
}
|
955
1047
|
case GQL_INPUT: {
|
956
|
-
|
1048
|
+
gqlArg a;
|
957
1049
|
|
958
1050
|
text = agoo_text_append(text, "input ", 6);
|
959
1051
|
text = agoo_text_append(text, type->name, -1);
|
1052
|
+
text = append_dir_use(text, type->dir);
|
960
1053
|
text = agoo_text_append(text, " {\n", 3);
|
961
|
-
for (
|
962
|
-
text =
|
1054
|
+
for (a = type->args; NULL != a; a = a->next) {
|
1055
|
+
text = arg_sdl(text, a, with_desc, NULL == a->next);
|
963
1056
|
}
|
964
1057
|
text = agoo_text_append(text, "}\n", 2);
|
965
1058
|
break;
|
@@ -1027,6 +1120,9 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1027
1120
|
for (bucket = buckets, i = 0; i < BUCKET_SIZE; bucket++, i++) {
|
1028
1121
|
for (s = *bucket; NULL != s; s = s->next) {
|
1029
1122
|
type = s->type;
|
1123
|
+
if (GQL_LIST == type->kind) {
|
1124
|
+
continue;
|
1125
|
+
}
|
1030
1126
|
if (!all && type->core) {
|
1031
1127
|
continue;
|
1032
1128
|
}
|
@@ -1040,6 +1136,9 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1040
1136
|
for (bucket = buckets, i = 0; i < BUCKET_SIZE; bucket++, i++) {
|
1041
1137
|
for (s = *bucket; NULL != s; s = s->next) {
|
1042
1138
|
type = s->type;
|
1139
|
+
if (GQL_LIST == type->kind) {
|
1140
|
+
continue;
|
1141
|
+
}
|
1043
1142
|
if (!all && type->core) {
|
1044
1143
|
continue;
|
1045
1144
|
}
|
@@ -1054,7 +1153,10 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1054
1153
|
}
|
1055
1154
|
}
|
1056
1155
|
}
|
1057
|
-
for (d =
|
1156
|
+
for (d = gql_directives; NULL != d; d = d->next) {
|
1157
|
+
if (!all && d->core) {
|
1158
|
+
continue;
|
1159
|
+
}
|
1058
1160
|
text = agoo_text_append(text, "\n", 1);
|
1059
1161
|
text = gql_directive_sdl(text, d, with_desc);
|
1060
1162
|
text = agoo_text_append(text, "\n", 1);
|
@@ -1062,6 +1164,362 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1062
1164
|
return text;
|
1063
1165
|
}
|
1064
1166
|
|
1167
|
+
gqlDirUse
|
1168
|
+
gql_dir_use_create(agooErr err, const char *name) {
|
1169
|
+
gqlDirUse use;
|
1170
|
+
|
1171
|
+
if (NULL == (use = (gqlDirUse)AGOO_MALLOC(sizeof(struct _gqlDirUse)))) {
|
1172
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a directive useage.");
|
1173
|
+
} else {
|
1174
|
+
if (NULL == (use->dir = assure_directive(err, name))) {
|
1175
|
+
return NULL;
|
1176
|
+
}
|
1177
|
+
use->next = NULL;
|
1178
|
+
use->args = NULL;
|
1179
|
+
}
|
1180
|
+
return use;
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
int
|
1184
|
+
gql_dir_use_arg(agooErr err, gqlDirUse use, const char *key, gqlValue value) {
|
1185
|
+
gqlLink link = gql_link_create(err, key, value);
|
1186
|
+
|
1187
|
+
if (NULL == link) {
|
1188
|
+
return err->code;
|
1189
|
+
}
|
1190
|
+
link->next = use->args;
|
1191
|
+
use->args = link;
|
1192
|
+
|
1193
|
+
return AGOO_ERR_OK;
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
void
|
1197
|
+
gql_type_directive_use(gqlType type, gqlDirUse use) {
|
1198
|
+
if (NULL == type->dir) {
|
1199
|
+
type->dir = use;
|
1200
|
+
} else {
|
1201
|
+
gqlDirUse u = type->dir;
|
1202
|
+
|
1203
|
+
for (; NULL != u->next; u = u->next) {
|
1204
|
+
}
|
1205
|
+
u->next = use;
|
1206
|
+
}
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
gqlFrag
|
1210
|
+
gql_fragment_create(agooErr err, const char *name, gqlType on) {
|
1211
|
+
gqlFrag frag = (gqlFrag)AGOO_MALLOC(sizeof(struct _gqlFrag));
|
1212
|
+
|
1213
|
+
if (NULL == frag) {
|
1214
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "fragment creation failed. %s:%d", __FILE__, __LINE__);
|
1215
|
+
} else {
|
1216
|
+
frag->next = NULL;
|
1217
|
+
if (NULL != name) {
|
1218
|
+
if (NULL == (frag->name = AGOO_STRDUP(name))) {
|
1219
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup of fragment name failed. %s:%d", __FILE__, __LINE__);
|
1220
|
+
return NULL;
|
1221
|
+
}
|
1222
|
+
} else {
|
1223
|
+
frag->name = NULL;
|
1224
|
+
}
|
1225
|
+
frag->dir = NULL;
|
1226
|
+
frag->on = on;
|
1227
|
+
frag->sels = NULL;
|
1228
|
+
}
|
1229
|
+
return frag;
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
int
|
1233
|
+
gql_validate(agooErr err) {
|
1234
|
+
|
1235
|
+
// TBD
|
1236
|
+
// list members all the same or attempt to coerce
|
1237
|
+
// check all validation rules in doc that are not covered in the parsing
|
1238
|
+
// check the directive us in specified locations only
|
1239
|
+
// set types if they are not already set or error out
|
1240
|
+
|
1241
|
+
return AGOO_ERR_OK;
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
gqlDoc
|
1245
|
+
gql_doc_create(agooErr err) {
|
1246
|
+
gqlDoc doc = (gqlDoc)AGOO_MALLOC(sizeof(struct _gqlDoc));
|
1247
|
+
|
1248
|
+
if (NULL == doc) {
|
1249
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "GraphQL Document creation failed. %s:%d", __FILE__, __LINE__);
|
1250
|
+
} else {
|
1251
|
+
doc->ops = NULL;
|
1252
|
+
doc->vars = NULL;
|
1253
|
+
doc->frags = NULL;
|
1254
|
+
}
|
1255
|
+
return doc;
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
gqlOp
|
1259
|
+
gql_op_create(agooErr err, const char *name, gqlOpKind kind) {
|
1260
|
+
gqlOp op = (gqlOp)AGOO_MALLOC(sizeof(struct _gqlOp));
|
1261
|
+
|
1262
|
+
if (NULL == op) {
|
1263
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "GraphQL Operation creation failed. %s:%d", __FILE__, __LINE__);
|
1264
|
+
} else {
|
1265
|
+
op->next = NULL;
|
1266
|
+
if (NULL != name && '\0' != *name) {
|
1267
|
+
if (NULL == (op->name = AGOO_STRDUP(name))) {
|
1268
|
+
agoo_err_set(err, AGOO_ERR_MEMORY, "strdup of operation name failed. %s:%d", __FILE__, __LINE__);
|
1269
|
+
return NULL;
|
1270
|
+
}
|
1271
|
+
} else {
|
1272
|
+
op->name = NULL;
|
1273
|
+
}
|
1274
|
+
op->vars = NULL;
|
1275
|
+
op->dir = NULL;
|
1276
|
+
op->sels = NULL;
|
1277
|
+
op->kind = kind;
|
1278
|
+
}
|
1279
|
+
return op;
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
static void
|
1283
|
+
var_destroy(gqlVar var) {
|
1284
|
+
AGOO_FREE((char*)var->name);
|
1285
|
+
if (NULL != var->value) {
|
1286
|
+
gql_value_destroy(var->value);
|
1287
|
+
}
|
1288
|
+
AGOO_FREE(var);
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
static void
|
1292
|
+
sel_arg_destroy(gqlSelArg arg) {
|
1293
|
+
AGOO_FREE((char*)arg->name);
|
1294
|
+
if (NULL != arg->value) {
|
1295
|
+
gql_value_destroy(arg->value);
|
1296
|
+
}
|
1297
|
+
AGOO_FREE(arg);
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
static void
|
1301
|
+
sel_destroy(gqlSel sel) {
|
1302
|
+
gqlSelArg arg;
|
1303
|
+
gqlSel s;
|
1304
|
+
|
1305
|
+
AGOO_FREE((char*)sel->alias);
|
1306
|
+
AGOO_FREE((char*)sel->name);
|
1307
|
+
while (NULL != (arg = sel->args)) {
|
1308
|
+
sel->args = arg->next;
|
1309
|
+
sel_arg_destroy(arg);
|
1310
|
+
}
|
1311
|
+
free_dir_uses(sel->dir);
|
1312
|
+
while (NULL != (s = sel->sels)) {
|
1313
|
+
sel->sels = s->next;
|
1314
|
+
sel_destroy(s);
|
1315
|
+
}
|
1316
|
+
AGOO_FREE((char*)sel->frag);
|
1317
|
+
if (NULL != sel->inline_frag) {
|
1318
|
+
gql_frag_destroy(sel->inline_frag);
|
1319
|
+
}
|
1320
|
+
AGOO_FREE(sel);
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
void
|
1324
|
+
gql_op_destroy(gqlOp op) {
|
1325
|
+
gqlSel sel;
|
1326
|
+
gqlVar var;
|
1327
|
+
|
1328
|
+
AGOO_FREE((char*)op->name);
|
1329
|
+
while (NULL != (var = op->vars)) {
|
1330
|
+
op->vars = var->next;
|
1331
|
+
var_destroy(var);
|
1332
|
+
}
|
1333
|
+
free_dir_uses(op->dir);
|
1334
|
+
while (NULL != (sel = op->sels)) {
|
1335
|
+
op->sels = sel->next;
|
1336
|
+
sel_destroy(sel);
|
1337
|
+
}
|
1338
|
+
AGOO_FREE(op);
|
1339
|
+
}
|
1340
|
+
|
1341
|
+
void
|
1342
|
+
gql_frag_destroy(gqlFrag frag) {
|
1343
|
+
gqlSel sel;
|
1344
|
+
|
1345
|
+
AGOO_FREE((char*)frag->name);
|
1346
|
+
free_dir_uses(frag->dir);
|
1347
|
+
while (NULL != (sel = frag->sels)) {
|
1348
|
+
frag->sels = sel->next;
|
1349
|
+
sel_destroy(sel);
|
1350
|
+
}
|
1351
|
+
AGOO_FREE(frag);
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
void
|
1355
|
+
gql_doc_destroy(gqlDoc doc) {
|
1356
|
+
gqlOp op;
|
1357
|
+
gqlFrag frag;
|
1358
|
+
gqlVar var;
|
1359
|
+
|
1360
|
+
while (NULL != (op = doc->ops)) {
|
1361
|
+
doc->ops = op->next;
|
1362
|
+
gql_op_destroy(op);
|
1363
|
+
}
|
1364
|
+
while (NULL != (var = doc->vars)) {
|
1365
|
+
doc->vars = var->next;
|
1366
|
+
var_destroy(var);
|
1367
|
+
}
|
1368
|
+
while (NULL != (frag = doc->frags)) {
|
1369
|
+
doc->frags = frag->next;
|
1370
|
+
gql_frag_destroy(frag);
|
1371
|
+
}
|
1372
|
+
AGOO_FREE(doc);
|
1373
|
+
}
|
1374
|
+
|
1375
|
+
static agooText
|
1376
|
+
sel_sdl(agooText text, gqlSel sel, int depth) {
|
1377
|
+
int indent = depth * 2;
|
1378
|
+
|
1379
|
+
if ((int)sizeof(spaces) <= indent) {
|
1380
|
+
indent = sizeof(spaces) - 1;
|
1381
|
+
}
|
1382
|
+
text = agoo_text_append(text, spaces, indent);
|
1383
|
+
if (NULL != sel->frag) {
|
1384
|
+
text = agoo_text_append(text, "...", 3);
|
1385
|
+
text = agoo_text_append(text, sel->frag, -1);
|
1386
|
+
text = append_dir_use(text, sel->dir);
|
1387
|
+
} else if (NULL != sel->inline_frag) {
|
1388
|
+
if (NULL == sel->inline_frag->on) {
|
1389
|
+
text = agoo_text_append(text, "...", 3);
|
1390
|
+
} else {
|
1391
|
+
text = agoo_text_append(text, "... on ", 7);
|
1392
|
+
text = agoo_text_append(text, sel->inline_frag->on->name, -1);
|
1393
|
+
}
|
1394
|
+
text = append_dir_use(text, sel->dir);
|
1395
|
+
if (NULL != sel->inline_frag->sels) {
|
1396
|
+
gqlSel s;
|
1397
|
+
int d2 = depth + 1;
|
1398
|
+
|
1399
|
+
text = agoo_text_append(text, " {\n", 3);
|
1400
|
+
for (s = sel->inline_frag->sels; NULL != s; s = s->next) {
|
1401
|
+
text = sel_sdl(text, s, d2);
|
1402
|
+
}
|
1403
|
+
text = agoo_text_append(text, spaces, indent);
|
1404
|
+
text = agoo_text_append(text, "}", 1);
|
1405
|
+
}
|
1406
|
+
} else {
|
1407
|
+
if (NULL != sel->alias) {
|
1408
|
+
text = agoo_text_append(text, sel->alias, -1);
|
1409
|
+
text = agoo_text_append(text, ": ", 2);
|
1410
|
+
}
|
1411
|
+
text = agoo_text_append(text, sel->name, -1);
|
1412
|
+
if (NULL != sel->args) {
|
1413
|
+
gqlSelArg arg;
|
1414
|
+
|
1415
|
+
text = agoo_text_append(text, "(", 1);
|
1416
|
+
for (arg = sel->args; NULL != arg; arg = arg->next) {
|
1417
|
+
text = agoo_text_append(text, arg->name, -1);
|
1418
|
+
text = agoo_text_append(text, ": ", 2);
|
1419
|
+
if (NULL != arg->var) {
|
1420
|
+
text = agoo_text_append(text, "$", 1);
|
1421
|
+
text = agoo_text_append(text, arg->var->name, -1);
|
1422
|
+
} else if (NULL != arg->value) {
|
1423
|
+
text = gql_value_sdl(text, arg->value, 0, 0);
|
1424
|
+
} else {
|
1425
|
+
text = agoo_text_append(text, "null", 4);
|
1426
|
+
}
|
1427
|
+
if (NULL != arg->next) {
|
1428
|
+
text = agoo_text_append(text, ", ", 2);
|
1429
|
+
}
|
1430
|
+
}
|
1431
|
+
text = agoo_text_append(text, ")", 1);
|
1432
|
+
}
|
1433
|
+
text = append_dir_use(text, sel->dir);
|
1434
|
+
if (NULL != sel->sels) {
|
1435
|
+
gqlSel s;
|
1436
|
+
int d2 = depth + 1;
|
1437
|
+
|
1438
|
+
text = agoo_text_append(text, " {\n", 3);
|
1439
|
+
for (s = sel->sels; NULL != s; s = s->next) {
|
1440
|
+
text = sel_sdl(text, s, d2);
|
1441
|
+
}
|
1442
|
+
text = agoo_text_append(text, spaces, indent);
|
1443
|
+
text = agoo_text_append(text, "}", 1);
|
1444
|
+
}
|
1445
|
+
}
|
1446
|
+
text = agoo_text_append(text, "\n", 1);
|
1447
|
+
|
1448
|
+
return text;
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
static agooText
|
1452
|
+
op_sdl(agooText text, gqlOp op) {
|
1453
|
+
gqlSel sel;
|
1454
|
+
|
1455
|
+
text = agoo_text_append(text, "query", 5);
|
1456
|
+
if (NULL != op->name) {
|
1457
|
+
text = agoo_text_append(text, " ", 1);
|
1458
|
+
text = agoo_text_append(text, op->name, -1);
|
1459
|
+
}
|
1460
|
+
if (NULL != op->vars) {
|
1461
|
+
gqlVar var;
|
1462
|
+
|
1463
|
+
text = agoo_text_append(text, "(", 1);
|
1464
|
+
for (var = op->vars; NULL != var; var = var->next) {
|
1465
|
+
text = agoo_text_append(text, "$", 1);
|
1466
|
+
text = agoo_text_append(text, var->name, -1);
|
1467
|
+
text = agoo_text_append(text, ": ", 2);
|
1468
|
+
|
1469
|
+
text = agoo_text_append(text, var->type->name, -1);
|
1470
|
+
if (NULL != var->value) {
|
1471
|
+
text = agoo_text_append(text, " = ", 3);
|
1472
|
+
text = gql_value_sdl(text, var->value, 0, 0);
|
1473
|
+
}
|
1474
|
+
if (NULL != var->next) {
|
1475
|
+
text = agoo_text_append(text, ", ", 2);
|
1476
|
+
}
|
1477
|
+
}
|
1478
|
+
text = agoo_text_append(text, ")", 1);
|
1479
|
+
}
|
1480
|
+
text = append_dir_use(text, op->dir);
|
1481
|
+
|
1482
|
+
text = agoo_text_append(text, " {\n", 3);
|
1483
|
+
for (sel = op->sels; NULL != sel; sel = sel->next) {
|
1484
|
+
text = sel_sdl(text, sel, 1);
|
1485
|
+
}
|
1486
|
+
text = agoo_text_append(text, "}\n", 2);
|
1487
|
+
|
1488
|
+
return text;
|
1489
|
+
}
|
1490
|
+
|
1491
|
+
static agooText
|
1492
|
+
frag_sdl(agooText text, gqlFrag frag) {
|
1493
|
+
gqlSel sel;
|
1494
|
+
|
1495
|
+
text = agoo_text_append(text, "fragment ", 9);
|
1496
|
+
text = agoo_text_append(text, frag->name, -1);
|
1497
|
+
text = agoo_text_append(text, " on ", 4);
|
1498
|
+
text = agoo_text_append(text, frag->on->name, -1);
|
1499
|
+
text = append_dir_use(text, frag->dir);
|
1500
|
+
text = agoo_text_append(text, " {\n", 3);
|
1501
|
+
for (sel = frag->sels; NULL != sel; sel = sel->next) {
|
1502
|
+
text = sel_sdl(text, sel, 1);
|
1503
|
+
}
|
1504
|
+
text = agoo_text_append(text, "}\n", 2);
|
1505
|
+
|
1506
|
+
return text;
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
agooText
|
1510
|
+
gql_doc_sdl(gqlDoc doc, agooText text) {
|
1511
|
+
gqlOp op;
|
1512
|
+
gqlFrag frag;
|
1513
|
+
|
1514
|
+
for (op = doc->ops; NULL != op; op = op->next) {
|
1515
|
+
op_sdl(text, op);
|
1516
|
+
}
|
1517
|
+
for (frag = doc->frags; NULL != frag; frag = frag->next) {
|
1518
|
+
text = frag_sdl(text, frag);
|
1519
|
+
}
|
1520
|
+
return text;
|
1521
|
+
}
|
1522
|
+
|
1065
1523
|
void
|
1066
1524
|
gql_dump_hook(agooReq req) {
|
1067
1525
|
char buf[256];
|
@@ -1086,11 +1544,32 @@ gql_dump_hook(agooReq req) {
|
|
1086
1544
|
agoo_res_set_message(req->res, text);
|
1087
1545
|
}
|
1088
1546
|
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1547
|
+
gqlField
|
1548
|
+
gql_type_get_field(gqlType type, const char *field) {
|
1549
|
+
gqlField f;
|
1550
|
+
|
1551
|
+
if (NULL == type) {
|
1552
|
+
return NULL;
|
1553
|
+
}
|
1554
|
+
switch (type->kind) {
|
1555
|
+
case GQL_OBJECT:
|
1556
|
+
case GQL_INTERFACE:
|
1557
|
+
for (f = type->fields; NULL != f; f = f->next) {
|
1558
|
+
if (0 == strcmp(field, f->name)) {
|
1559
|
+
return f;
|
1560
|
+
}
|
1561
|
+
}
|
1562
|
+
break;
|
1563
|
+
case GQL_UNION:
|
1564
|
+
// TBD
|
1565
|
+
break;
|
1566
|
+
case GQL_LIST:
|
1567
|
+
return gql_type_get_field(type->base, field);
|
1568
|
+
break;
|
1569
|
+
default:
|
1570
|
+
// TBD
|
1571
|
+
break;
|
1572
|
+
}
|
1573
|
+
return NULL;
|
1096
1574
|
}
|
1575
|
+
|