• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MinaProtocol / mina / 2863

05 Nov 2024 06:20PM UTC coverage: 30.754% (-16.6%) from 47.311%
2863

push

buildkite

web-flow
Merge pull request #16296 from MinaProtocol/dkijania/more_multi_jobs

more multi jobs in CI

20276 of 65930 relevant lines covered (30.75%)

8631.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.76
/src/lib/graphql_wrapper/graphql_wrapper.ml
1
(**
2
   This file provides a wrapper around an ocaml-graphql-server [Schema] module,
3
   in order to build [to_json] functions for query [fields].
4
   These can later be used to serialize queries.
5

6
   - The [Arg.scalar] function has a new [~to_json] argument that is
7
   morally the inverse of [coerce].  The most common case where these
8
   functions are not inverse of one another is when the [coerce] function can fail
9
   during parsing and return a [result] type, but it does not make
10
   sense for the [to_json] function to take a result type as input.
11

12
   - The [Arg.obj] function has a new [~split] argument, which is also morally the inverse of coerce:
13
     while the [coerce] function for [obj] arguments builds an ocaml value from the fields of the objects,
14
   the [split] describes how to split an ocaml value into these fields.
15

16
    The [split] argument is used as such:
17
          {[
18
          let add_payment_reciept_input =
19
              obj "AddPaymentReceiptInput"
20
              ~coerce:(fun payment added_time -> { payment; added_time })
21
              ~split:(fun f (t : t) -> f t.payment t.added_time)
22
              ~fields:[...]
23
          ]}
24

25
    The [to_json] function from the [add_payment_reciept_input] can then be used as such :
26
    {[let input_as_json = add_payment_reciept_input.to_json
27
                          {payment = "..."; added_time = "..."}]}
28
 *)
29

30
module Make (Schema : Graphql_intf.Schema) = struct
31
  (** wrapper around the [enum_value] type *)
32
  type 'a enum_value =
33
    { as_string : string; value : 'a; enum_value : 'a Schema.enum_value }
34

35
  (** wrapper around the [enum_value] function *)
36
  let enum_value ?doc ?deprecated as_string ~value =
37
    { as_string
21✔
38
    ; value
39
    ; enum_value = Schema.enum_value ?doc ?deprecated as_string ~value
21✔
40
    }
41

42
  module Arg = struct
43
    (** wrapper around the [Arg.arg_typ] type *)
44
    type ('obj_arg, 'a) arg_typ =
45
      { arg_typ : 'obj_arg Schema.Arg.arg_typ; to_json : 'a -> Yojson.Basic.t }
46

47
    (** wrapper around the [Arg.arg] type *)
48
    type ('obj_arg, 'a) arg =
49
      | Arg :
50
          { name : string; doc : string option; typ : ('obj_arg, 'a) arg_typ }
51
          -> ('obj_arg, 'a) arg
52
      | DefaultArg :
53
          { name : string
54
          ; doc : string option
55
          ; typ : ('obj_arg option, 'a) arg_typ
56
          ; default : 'obj_arg
57
          }
58
          -> ('obj_arg, 'a) arg
59

60
    (**
61
       Wrapper around the [Arg.arg_list] type.
62

63
       The ocaml-graphql-server library uses this gadt type for lists of
64
       arguments used with [fields] and [obj] argument types.
65

66
       This enables to the correct types for the [coerce] and [resolve] functions,
67
       in the ['args] parameter below.
68

69
       We wrap around this and do the same thing to build the types of the [to_json] functions.
70
     *)
71

72
    type (_, _, _, _, _) args =
73
      | [] : ('ctx, 'out, 'out, string * Yojson.Basic.t, Yojson.Basic.t) args
74
      | ( :: ) :
75
          ('a, 'input) arg
76
          * ('ctx, 'out, 'args, 'field_to_json, 'obj_to_json) args
77
          -> ( 'ctx
78
             , 'out
79
             , 'a -> 'args
80
             , 'input -> 'field_to_json
81
             , 'input -> 'obj_to_json )
82
             args
83

84
    (** [field_to_json] builds the serializer function for a field, based on the list of its arguments.*)
85
    let rec field_to_json :
86
        type ctx out arg field_to_json obj_to_json.
87
           string
88
        -> (ctx, out, arg, field_to_json, obj_to_json) args
89
        -> (string * Yojson.Basic.t) list
90
        -> field_to_json =
91
     fun field_name l acc ->
92
      match l with
100✔
93
      | [] ->
45✔
94
          (field_name, `Assoc acc)
95
      | Arg { typ; name; _ } :: t ->
55✔
96
          fun x -> field_to_json field_name t ((name, typ.to_json x) :: acc)
×
97
      | DefaultArg { typ; name; _ } :: t ->
×
98
          fun x -> field_to_json field_name t ((name, typ.to_json x) :: acc)
×
99

100
    (** [arg_obj_to_json] builds the serializer function for an obj argument, based on the list of its fields.*)
101
    let rec arg_obj_to_json :
102
        type ctx out arg field_to_json obj_to_json.
103
           (ctx, out, arg, field_to_json, obj_to_json) args
104
        -> (string * Yojson.Basic.t) list
105
        -> obj_to_json =
106
     fun l acc ->
107
      match l with
24✔
108
      | [] ->
×
109
          `Assoc acc
110
      | Arg { name; typ; _ } :: t ->
24✔
111
          fun x -> arg_obj_to_json t ((name, typ.to_json x) :: acc)
×
112
      | DefaultArg { name; typ; _ } :: t ->
×
113
          fun x -> arg_obj_to_json t ((name, typ.to_json x) :: acc)
×
114

115
    (** extracts the wrapped [Arg.arg_list] to pass to ocaml-graphql-server functions *)
116
    let rec to_ocaml_graphql_server_args :
117
        type ctx out args_server field_to_json obj_to_json.
118
           (ctx, out, args_server, field_to_json, obj_to_json) args
119
        -> (out, args_server) Schema.Arg.arg_list = function
120
      | [] ->
124✔
121
          Schema.Arg.[]
122
      | Arg { name; doc; typ } :: t ->
159✔
123
          let graphql_arg = Schema.Arg.arg ?doc name ~typ:typ.arg_typ in
124
          Schema.Arg.(graphql_arg :: to_ocaml_graphql_server_args t)
159✔
125
      | DefaultArg { name; doc; typ; default } :: t ->
1✔
126
          let graphql_arg =
127
            Schema.Arg.arg' ?doc name ~typ:typ.arg_typ ~default
128
          in
129
          Schema.Arg.(graphql_arg :: to_ocaml_graphql_server_args t)
1✔
130

131
    let int =
132
      { arg_typ = Schema.Arg.int
133
      ; to_json = Json.json_of_option (fun i -> `Int i)
×
134
      }
135

136
    let scalar ?doc name ~coerce ~to_json =
137
      { arg_typ = Schema.Arg.scalar ?doc name ~coerce
16✔
138
      ; to_json = Json.json_of_option to_json
16✔
139
      }
140

141
    let string =
142
      { arg_typ = Schema.Arg.string
143
      ; to_json = Json.json_of_option (function s -> `String s)
×
144
      }
145

146
    let float =
147
      { arg_typ = Schema.Arg.float
148
      ; to_json = Json.json_of_option (function f -> `Float f)
×
149
      }
150

151
    let bool =
152
      { arg_typ = Schema.Arg.bool
153
      ; to_json = Json.json_of_option (function f -> `Bool f)
×
154
      }
155

156
    let guid =
157
      { arg_typ = Schema.Arg.guid
158
      ; to_json = Json.json_of_option (function s -> `String s)
×
159
      }
160

161
    let obj ?doc name ~fields ~coerce ~split =
162
      let build_obj_json = arg_obj_to_json fields [] in
24✔
163
      let gql_server_fields = to_ocaml_graphql_server_args fields in
24✔
164
      let arg_typ =
24✔
165
        Schema.Arg.obj name ?doc ~fields:gql_server_fields ~coerce
166
      in
167
      { arg_typ; to_json = Json.json_of_option @@ split build_obj_json }
24✔
168

169
    let non_null (arg_typ : _ arg_typ) =
170
      { arg_typ = Schema.Arg.non_null arg_typ.arg_typ
135✔
171
      ; to_json = (function x -> arg_typ.to_json (Some x))
×
172
      }
173

174
    let list (arg_typ : _ arg_typ) =
175
      { arg_typ = Schema.Arg.list arg_typ.arg_typ
18✔
176
      ; to_json =
177
          Json.json_of_option (function l -> `List (List.map arg_typ.to_json l))
×
178
      }
179

180
    (** wrapper around the enum arg_typ.
181
        For this type, the [to_json] function can be infered from the list of enum_value.*)
182
    let enum ?doc name ~(values : _ enum_value list) =
183
      let rec to_string (values : _ enum_value list) v =
2✔
184
        match values with
×
185
        | { as_string; value; _ } :: _ when value = v ->
×
186
            as_string
×
187
        | _ :: q ->
×
188
            to_string q v
189
        | _ ->
×
190
            failwith
191
            @@ Format.asprintf
×
192
                 "Could not convert GraphQL query argument to string for enum \
193
                  type <%s>. Was this argument declared via an enum_value ?"
194
                 name
195
      in
196
      let ocaml_graphql_server_values =
197
        List.map (function { enum_value; _ } -> enum_value) values
4✔
198
      in
199
      { arg_typ = Schema.Arg.enum ?doc name ~values:ocaml_graphql_server_values
2✔
200
      ; to_json = Json.json_of_option (fun v -> `String (to_string values v))
×
201
      }
202

203
    let arg ?doc name ~typ = Arg { name; typ; doc }
154✔
204

205
    let arg' ?doc name ~typ ~default = DefaultArg { name; typ; doc; default }
1✔
206
  end
207

208
  module Fields = struct
209
    (** a record contraining the ocaml-graphql-server [field], its [name]
210
        and a [to_string] function to be used when serializing a query *)
211
    type ('ctx, 'src, 'args_to_json, 'out, 'subquery) field =
212
      { field : ('ctx, 'src) Schema.field
213
      ; to_json : 'args_to_json
214
      ; name : string
215
      }
216

217
    (** wrapper around the [field] typ *)
218
    let field ?doc ?deprecated name ~typ ~(args : (_, 'out, _, _, _) Arg.args)
219
        ~resolve : (_, _, _, 'out, _) field =
220
      let to_json = Arg.field_to_json name args [] in
49✔
221
      let args = Arg.to_ocaml_graphql_server_args args in
49✔
222
      let field = Schema.field ?doc ?deprecated name ~args ~typ ~resolve in
49✔
223
      { name; field; to_json }
49✔
224

225
    (** wrapper around the [io_field] typ*)
226
    let io_field ?doc ?deprecated name ~typ
227
        ~(args : (_, 'out, _, _, _) Arg.args) ~resolve :
228
        (_, _, _, 'out, _) field =
229
      let to_json = Arg.field_to_json name args [] in
48✔
230
      let args = Arg.to_ocaml_graphql_server_args args in
48✔
231
      let field = Schema.io_field ?doc ?deprecated name ~args ~typ ~resolve in
48✔
232
      { name; field; to_json }
48✔
233
  end
234

235
  module Abstract_fields = struct
236
    type ('ctx, 'src, 'args_to_json, 'out, 'subquery) abstract_field =
237
      { field : Schema.abstract_field; to_json : 'args_to_json; name : string }
238

239
    (** wrapper around the [abstract_field] typ*)
240
    let abstract_field ?doc ?deprecated name ~typ
241
        ~(args : (_, 'out, _, _, _) Arg.args) :
242
        (_, _, _, 'out, _) abstract_field =
243
      let to_json = Arg.field_to_json name args [] in
×
244
      let args = Arg.to_ocaml_graphql_server_args args in
×
245
      let field = Schema.abstract_field ?doc ?deprecated name ~typ ~args in
×
246
      { name; field; to_json }
×
247
  end
248

249
  module Subscription_fields = struct
250
    (** A record contraining the ocaml-graphql-server [subscription_fields], its [name]
251
        and a [to_json] function to be used when serializing a query *)
252
    type ('ctx, 'src, 'args_to_json, 'out, 'subquery) subscription_field =
253
      { field : 'ctx Schema.subscription_field
254
      ; to_json : 'args_to_json
255
      ; name : string
256
      }
257

258
    (** wrapper around the [subscription_field] typ*)
259
    let subscription_field ?doc ?deprecated name ~typ
260
        ~(args : (_, 'out, _, _, _) Arg.args) ~resolve :
261
        (_, _, _, 'out, _) subscription_field =
262
      let to_json = Arg.field_to_json name args [] in
3✔
263
      let args = Arg.to_ocaml_graphql_server_args args in
3✔
264
      let field =
3✔
265
        Schema.subscription_field ?doc ?deprecated name ~args ~typ ~resolve
266
      in
267
      { name; field; to_json }
3✔
268
  end
269

270
  let field ?doc ?deprecated name ~typ ~args ~resolve =
271
    (Fields.field ?doc ?deprecated name ~typ ~args ~resolve).field
49✔
272

273
  let io_field ?doc ?deprecated name ~typ ~args ~resolve =
274
    (Fields.io_field ?doc ?deprecated name ~typ ~args ~resolve).field
48✔
275

276
  let subscription_field ?doc ?deprecated name ~typ ~args ~resolve =
277
    (Subscription_fields.subscription_field ?doc ?deprecated name ~typ ~args
3✔
278
       ~resolve )
279
      .field
280

281
  let abstract_field ?doc ?deprecated name ~typ ~args =
282
    (Abstract_fields.abstract_field ?doc ?deprecated name ~typ ~args).field
×
283

284
  let enum ?doc name ~values =
285
    Schema.enum ?doc name
5✔
286
      ~values:(List.map (function v -> v.enum_value) values)
5✔
287

288
  (** The [Propagated] module contains the parts of the Schema we do not modify *)
289
  module Propagated = struct
290
    let obj = Schema.obj
291

292
    let schema = Schema.schema
293

294
    let interface = Schema.interface
295

296
    let non_null = Schema.non_null
297

298
    let string = Schema.string
299

300
    let list = Schema.list
301

302
    let bool = Schema.bool
303

304
    let int = Schema.int
305

306
    type ('a, 'b) typ = ('a, 'b) Schema.typ
307

308
    let scalar = Schema.scalar
309

310
    type ('a, 'b) abstract_value = ('a, 'b) Schema.abstract_value
311

312
    let guid = Schema.guid
313

314
    let add_type = Schema.add_type
315

316
    let float = Schema.float
317

318
    type 'ctx resolve_info = 'ctx Schema.resolve_info =
319
      { ctx : 'ctx
320
      ; field : Graphql_parser.field
321
      ; fragments : Schema.fragment_map
322
      ; variables : Schema.variable_map
323
      }
324

325
    type 'a schema = 'a Schema.schema
326

327
    type ('a, 'b) field = ('a, 'b) Schema.field
328

329
    type 'a subscription_field = 'a Schema.subscription_field
330

331
    type deprecated = Schema.deprecated
332

333
    type variable_map = Schema.variable_map
334

335
    type fragment_map = Schema.fragment_map
336

337
    let execute = Schema.execute
338

339
    type 'a response = 'a Schema.response
340

341
    type variables = (string * Graphql_parser.const_value) list
342

343
    type abstract_field = Schema.abstract_field
344

345
    let union = Schema.union
346

347
    type ('a, 'b) abstract_typ = ('a, 'b) Schema.abstract_typ
348

349
    module StringMap = Schema.StringMap
350
    module Io = Schema.Io
351
  end
352

353
  include Propagated
354
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc