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

MinaProtocol / mina / 2903

15 Nov 2024 01:59PM UTC coverage: 36.723% (-25.0%) from 61.682%
2903

Pull #16342

buildkite

dkijania
Merge branch 'dkijania/remove_publish_job_from_pr_comp' into dkijania/remove_publish_job_from_pr_dev
Pull Request #16342: [DEV] Publish debians only on nightly and stable

15 of 40 new or added lines in 14 files covered. (37.5%)

15175 existing lines in 340 files now uncovered.

24554 of 66863 relevant lines covered (36.72%)

20704.91 hits per line

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

38.61
/src/lib/fields_derivers_graphql/fields_derivers_graphql.ml
1
open Core_kernel
21✔
2
open Fieldslib
3

4
module Graphql_raw = struct
5
  module Make (Schema : Graphql_intf.Schema) = struct
6
    module Args = struct
7
      module Input = struct
8
        type ('row, 'result, 'ty, 'nullable) t =
9
          < graphql_arg : (unit -> 'ty Schema.Arg.arg_typ) ref
10
          ; nullable_graphql_arg : (unit -> 'nullable Schema.Arg.arg_typ) ref
11
          ; map : ('ty -> 'result) ref
12
          ; skip : bool ref
13
          ; .. >
14
          as
15
          'row
16
      end
17

18
      module Acc = struct
19
        module T = struct
20
          type ('ty, 'fields) t_inner =
21
            { graphql_arg_fields : ('ty, 'fields) Schema.Arg.arg_list
22
            ; graphql_arg_coerce : 'fields
23
            }
24

25
          type 'ty t = Init | Acc : ('ty, 'fields) t_inner -> 'ty t
26
        end
27

28
        type ('row, 'result, 'ty, 'nullable) t =
29
          < graphql_arg_accumulator : 'result T.t ref ; .. > as 'row
30
          constraint
31
            ('row, 'c, 'ty, 'nullable) t =
32
            ('row, 'c, 'ty, 'nullable) Input.t
33
      end
34

35
      module Creator = struct
36
        type ('row, 'c, 'ty, 'nullable) t = < .. > as 'row
37
          constraint
38
            ('row, 'c, 'ty, 'nullable) t =
39
            ('row, 'c, 'ty, 'nullable) Input.t
40
      end
41

42
      module Output = struct
43
        type ('row, 'c, 'ty, 'nullable) t = < .. > as 'row
44
          constraint
45
            ('row, 'c, 'ty, 'nullable) t =
46
            ('row, 'c, 'ty, 'nullable) Input.t
47
      end
48

49
      let add_field (type f f' ty ty' nullable1 nullable2) ?skip_data
50
          ~t_fields_annots :
51
             ('f_row, f', f, nullable1) Input.t
52
          -> ([< `Read | `Set_and_create ], _, _) Field.t_with_perm
53
          -> ('row, ty', ty, nullable2) Acc.t
54
          -> (('row, ty', ty, nullable2) Creator.t -> f')
55
             * ('row_after, ty', ty, nullable2) Acc.t =
56
       fun f_input field acc ->
2,852✔
57
        let annotations =
2,852✔
58
          Fields_derivers.Annotations.Fields.of_annots t_fields_annots
59
            (Field.name field)
2,852✔
60
        in
61
        let ref_as_pipe = ref None in
2,852✔
62
        let name =
63
          Option.value annotations.name
64
            ~default:(Fields_derivers.name_under_to_camel field)
2,852✔
65
        in
66
        let () =
2,852✔
67
          let inner_acc = acc#graphql_arg_accumulator in
UNCOV
68
          if annotations.skip || !(f_input#skip) then ()
×
69
          else
70
            let arg =
2,852✔
71
              Schema.Arg.arg name ?doc:annotations.doc
72
                ~typ:(!(f_input#graphql_arg) ())
5,704✔
73
            in
74
            match !inner_acc with
2,852✔
75
            | Init ->
805✔
76
                inner_acc :=
77
                  Acc
78
                    { graphql_arg_coerce =
79
                        (fun x ->
80
                          ref_as_pipe := Some x ;
2,383✔
81
                          !(acc#graphql_creator) acc )
2,383✔
82
                    ; graphql_arg_fields = [ arg ]
83
                    }
84
            | Acc { graphql_arg_fields; graphql_arg_coerce } -> (
2,047✔
85
                match graphql_arg_fields with
86
                | [] ->
×
87
                    inner_acc :=
88
                      Acc
89
                        { graphql_arg_coerce =
90
                            (fun x ->
91
                              ref_as_pipe := Some x ;
×
92
                              !(acc#graphql_creator) acc )
×
93
                        ; graphql_arg_fields = [ arg ]
94
                        }
95
                | _ ->
2,047✔
96
                    inner_acc :=
97
                      Acc
98
                        { graphql_arg_coerce =
99
                            (fun x ->
100
                              ref_as_pipe := Some x ;
8,875✔
101
                              graphql_arg_coerce )
102
                        ; graphql_arg_fields = arg :: graphql_arg_fields
103
                        } )
104
        in
105
        ( (fun _creator_input ->
106
            !(f_input#map)
11,258✔
107
            @@
108
            if annotations.skip || !(f_input#skip) then
×
109
              match skip_data with
×
110
              | Some data ->
×
111
                  data
112
              | None ->
×
113
                  failwith
114
                    "If you are skipping a field but intend on building this \
115
                     field, you must provide skip_data to add_field!"
116
            else Option.value_exn !ref_as_pipe )
11,258✔
117
        , acc )
118

119
      let finish name ~t_toplevel_annots (type ty result nullable) :
805✔
120
             (('row, result, ty, nullable) Input.t -> result)
121
             * ('row, result, ty, nullable) Acc.t
122
          -> _ Output.t =
123
       fun (creator, acc) ->
124
        let annotations =
805✔
125
          Fields_derivers.Annotations.Top.of_annots ~name t_toplevel_annots
126
        in
127
        acc#graphql_creator := creator ;
805✔
128
        (acc#graphql_arg :=
805✔
129
           fun () ->
130
             match !(acc#graphql_arg_accumulator) with
392✔
131
             | Init ->
×
132
                 failwith "Graphql args need at least one field"
133
             | Acc { graphql_arg_fields; graphql_arg_coerce } ->
392✔
134
                 (* TODO: Figure out why the typechecker doesn't like this
135
                  * expression and remove Obj.magic. *)
136
                 Obj.magic
137
                 @@ Schema.Arg.(
138
                      obj ?doc:annotations.doc
392✔
139
                        (annotations.name ^ "Input")
140
                        ~fields:graphql_arg_fields ~coerce:graphql_arg_coerce
141
                      |> non_null) ) ;
392✔
142
        (acc#nullable_graphql_arg :=
805✔
143
           fun () ->
144
             match !(acc#graphql_arg_accumulator) with
322✔
145
             | Init ->
×
146
                 failwith "Graphql args need at least one field"
147
             | Acc { graphql_arg_fields; graphql_arg_coerce } ->
322✔
148
                 (* TODO: See above *)
149
                 Obj.magic
150
                 @@ Schema.Arg.(
151
                      obj ?doc:annotations.doc
322✔
152
                        (annotations.name ^ "Input")
153
                        ~fields:graphql_arg_fields ~coerce:graphql_arg_coerce)
154
        ) ;
155
        acc
156

157
      let skip obj =
158
        obj#skip := true ;
69✔
159
        (obj#graphql_arg :=
69✔
160
           fun () ->
161
             failwith "Unexpected: This obj#graphql_arg should be skipped" ) ;
×
162
        obj#map := Fn.id ;
69✔
163
        obj#graphql_arg_accumulator := !(obj#graphql_arg_accumulator) ;
69✔
164
        (obj#nullable_graphql_arg :=
69✔
165
           fun () ->
166
             failwith "Unexpected: This obj#graphql_arg should be skipped" ) ;
×
167
        obj
168

169
      let int obj =
170
        (obj#graphql_arg := fun () -> Schema.Arg.(non_null int)) ;
23✔
171
        obj#map := Fn.id ;
23✔
172
        obj#graphql_arg_accumulator := !(obj#graphql_arg_accumulator) ;
23✔
UNCOV
173
        (obj#nullable_graphql_arg := fun () -> Schema.Arg.int) ;
×
174
        obj
175

176
      let string obj =
177
        (obj#graphql_arg := fun () -> Schema.Arg.(non_null string)) ;
23✔
178
        obj#map := Fn.id ;
92✔
179
        obj#graphql_arg_accumulator := !(obj#graphql_arg_accumulator) ;
92✔
180
        (obj#nullable_graphql_arg := fun () -> Schema.Arg.string) ;
46✔
181
        obj
182

183
      let bool obj =
184
        (obj#graphql_arg := fun () -> Schema.Arg.(non_null bool)) ;
161✔
185
        obj#map := Fn.id ;
253✔
186
        obj#graphql_arg_accumulator := !(obj#graphql_arg_accumulator) ;
253✔
187
        (obj#nullable_graphql_arg := fun () -> Schema.Arg.bool) ;
46✔
188
        obj
189

190
      let list x obj : (_, 'result list, 'input_type list, _) Input.t =
191
        (obj#graphql_arg :=
207✔
192
           fun () -> Schema.Arg.(non_null (list (!(x#graphql_arg) ()))) ) ;
253✔
193
        obj#map := List.map ~f:!(x#map) ;
207✔
194
        obj#graphql_arg_accumulator := !(x#graphql_arg_accumulator) ;
207✔
195
        (obj#nullable_graphql_arg :=
207✔
196
           fun () -> Schema.Arg.(list (!(x#graphql_arg) ())) ) ;
×
197
        obj
198

199
      let option (x : (_, 'result, 'input_type, _) Input.t) obj =
200
        obj#graphql_arg := !(x#nullable_graphql_arg) ;
851✔
201
        obj#nullable_graphql_arg := !(x#nullable_graphql_arg) ;
851✔
202
        obj#map := Option.map ~f:!(x#map) ;
851✔
203
        obj#graphql_arg_accumulator := !(x#graphql_arg_accumulator) ;
851✔
204
        obj
205

206
      let map ~(f : 'c -> 'd) (x : (_, 'c, 'input_type, _) Input.t) obj :
207
          (_, 'd, 'input_type, _) Input.t =
208
        obj#graphql_arg := !(x#graphql_arg) ;
989✔
209
        (obj#map := fun a -> f (!(x#map) a)) ;
×
210
        obj#nullable_graphql_arg := !(x#nullable_graphql_arg) ;
989✔
211
        obj#graphql_arg_accumulator := !(x#graphql_arg_accumulator) ;
989✔
212
        obj
213
    end
214

215
    module Fields = struct
216
      module Input = struct
217
        module T = struct
218
          type 'input_type t =
219
            { run : 'ctx. unit -> ('ctx, 'input_type) Schema.typ }
220
        end
221

222
        type ('input_type, 'a, 'c, 'nullable) t =
223
          < graphql_fields : 'input_type T.t ref
224
          ; contramap : ('c -> 'input_type) ref
225
          ; nullable_graphql_fields : 'nullable T.t ref
226
          ; .. >
227
          as
228
          'a
229
      end
230

231
      module Accumulator = struct
232
        module T = struct
233
          type 'input_type t =
234
            { run : 'ctx. unit -> ('ctx, 'input_type) Schema.field option }
235
        end
236

237
        (** thunks generating the schema in reverse *)
238
        type ('input_type, 'a, 'c, 'nullable) t =
239
          < graphql_fields_accumulator : 'c T.t list ref ; .. > as 'a
240
          constraint
241
            ('input_type, 'a, 'c, 'nullable) t =
242
            ('input_type, 'a, 'c, 'nullable) Input.t
243
      end
244

245
      let add_field (type f input_type orig nullable c' nullable')
246
          ~t_fields_annots :
247
             (orig, 'a, f, nullable) Input.t
248
          -> ([< `Read | `Set_and_create ], c', f) Fieldslib.Field.t_with_perm
249
          -> (input_type, 'row2, c', nullable') Accumulator.t
250
          -> (_ -> f) * (input_type, 'row2, c', nullable') Accumulator.t =
251
       fun t_field field acc ->
2,852✔
252
        let annotations =
2,852✔
253
          Fields_derivers.Annotations.Fields.of_annots t_fields_annots
254
            (Field.name field)
2,852✔
255
        in
256
        let rest = !(acc#graphql_fields_accumulator) in
2,852✔
257
        acc#graphql_fields_accumulator :=
2,852✔
258
          { Accumulator.T.run =
259
              (fun () ->
UNCOV
260
                if annotations.skip || !(t_field#skip) then None
×
261
                else
UNCOV
262
                  Schema.field
×
UNCOV
263
                    (Option.value annotations.name
×
UNCOV
264
                       ~default:(Fields_derivers.name_under_to_camel field) )
×
265
                    ~args:Schema.Arg.[]
266
                    ?doc:annotations.doc
267
                    ~deprecated:
UNCOV
268
                      ( Option.map annotations.deprecated ~f:(fun msg ->
×
269
                            Schema.Deprecated (Some msg) )
×
UNCOV
270
                      |> Option.value ~default:Schema.NotDeprecated )
×
UNCOV
271
                    ~typ:(!(t_field#graphql_fields).Input.T.run ())
×
272
                    ~resolve:(fun _ x ->
UNCOV
273
                      !(t_field#contramap) (Field.get field x) )
×
274
                  |> Option.return )
275
          }
276
          :: rest ;
277
        ((fun _ -> failwith "Unused"), acc)
×
278

279
      let finish name ~t_toplevel_annots ((_creator, obj) : 'u * _ Accumulator.t)
280
          : _ Input.t =
281
        let annotations =
805✔
282
          Fields_derivers.Annotations.Top.of_annots ~name t_toplevel_annots
283
        in
284
        let graphql_fields_accumulator = !(obj#graphql_fields_accumulator) in
805✔
285
        let graphql_fields =
286
          { Input.T.run =
287
              (fun () ->
UNCOV
288
                Schema.obj annotations.name ?doc:annotations.doc
×
289
                  ~fields:(fun _ ->
UNCOV
290
                    List.rev
×
UNCOV
291
                    @@ List.filter_map graphql_fields_accumulator ~f:(fun g ->
×
UNCOV
292
                           g.Accumulator.T.run () ) )
×
293
                |> Schema.non_null )
294
          }
295
        in
296
        let nullable_graphql_fields =
297
          { Input.T.run =
298
              (fun () ->
UNCOV
299
                Schema.obj annotations.name ?doc:annotations.doc
×
300
                  ~fields:(fun _ ->
UNCOV
301
                    List.rev
×
UNCOV
302
                    @@ List.filter_map graphql_fields_accumulator ~f:(fun g ->
×
UNCOV
303
                           g.Accumulator.T.run () ) ) )
×
304
          }
305
        in
306
        obj#graphql_fields := graphql_fields ;
805✔
307
        obj#nullable_graphql_fields := nullable_graphql_fields ;
805✔
308
        obj#contramap := Fn.id ;
805✔
309
        obj
310

311
      let skip obj =
312
        (obj#graphql_fields :=
69✔
313
           Input.T.
314
             { run =
315
                 (fun () ->
316
                   failwith
×
317
                     "Unexpected: This obj#graphql_fields should be skipped" )
318
             } ) ;
319
        obj#contramap := Fn.id ;
69✔
320
        obj#graphql_fields_accumulator := !(obj#graphql_fields_accumulator) ;
69✔
321
        (obj#nullable_graphql_fields :=
69✔
322
           Input.T.
323
             { run =
324
                 (fun () ->
325
                   failwith
×
326
                     "Unexpected: This obj#nullable_graphql_fields should be \
327
                      skipped" )
328
             } ) ;
329
        obj
330

331
      let int obj =
332
        (obj#graphql_fields :=
23✔
UNCOV
333
           Input.T.{ run = (fun () -> Schema.(non_null int)) } ) ;
×
334
        obj#contramap := Fn.id ;
23✔
335
        obj#graphql_fields_accumulator := !(obj#graphql_fields_accumulator) ;
23✔
UNCOV
336
        (obj#nullable_graphql_fields := Input.T.{ run = (fun () -> Schema.int) }) ;
×
337
        obj
338

339
      let string obj =
340
        (obj#graphql_fields :=
92✔
UNCOV
341
           Input.T.{ run = (fun () -> Schema.(non_null string)) } ) ;
×
342
        obj#contramap := Fn.id ;
92✔
343
        obj#graphql_fields_accumulator := !(obj#graphql_fields_accumulator) ;
92✔
344
        (obj#nullable_graphql_fields :=
92✔
UNCOV
345
           Input.T.{ run = (fun () -> Schema.string) } ) ;
×
346
        obj
347

348
      let bool obj =
349
        (obj#graphql_fields :=
253✔
UNCOV
350
           Input.T.{ run = (fun () -> Schema.(non_null bool)) } ) ;
×
351
        obj#contramap := Fn.id ;
253✔
352
        obj#graphql_fields_accumulator := !(obj#graphql_fields_accumulator) ;
253✔
353
        (obj#nullable_graphql_fields :=
253✔
UNCOV
354
           Input.T.{ run = (fun () -> Schema.bool) } ) ;
×
355
        obj
356

357
      let list x obj : ('input_type list, _, _, _) Input.t =
358
        (obj#graphql_fields :=
207✔
359
           Input.T.
360
             { run =
361
                 (fun () ->
UNCOV
362
                   Schema.(non_null (list (!(x#graphql_fields).run ()))) )
×
363
             } ) ;
364
        obj#contramap := List.map ~f:!(x#contramap) ;
207✔
365
        obj#graphql_fields_accumulator := !(x#graphql_fields_accumulator) ;
207✔
366
        (obj#nullable_graphql_fields :=
207✔
367
           Input.T.
368
             { run = (fun () -> Schema.(list (!(x#graphql_fields).run ()))) } ) ;
×
369
        obj
370

371
      let option (x : ('input_type, 'b, 'c, 'nullable) Input.t) obj :
372
          ('input_type option, _, 'c option, _) Input.t =
373
        obj#graphql_fields := !(x#nullable_graphql_fields) ;
851✔
374
        obj#nullable_graphql_fields := !(x#nullable_graphql_fields) ;
851✔
375
        obj#contramap := Option.map ~f:!(x#contramap) ;
851✔
376
        obj#graphql_fields_accumulator := !(x#graphql_fields_accumulator) ;
851✔
377
        obj
378

379
      let contramap ~(f : 'd -> 'c)
380
          (x : ('input_type, 'b, 'c, 'nullable) Input.t) obj :
381
          ('input_type, _, 'd, _) Input.t =
382
        obj#graphql_fields := !(x#graphql_fields) ;
989✔
UNCOV
383
        (obj#contramap := fun a -> !(x#contramap) (f a)) ;
×
384
        obj#nullable_graphql_fields := !(x#nullable_graphql_fields) ;
989✔
385
        obj#graphql_fields_accumulator := !(x#graphql_fields_accumulator) ;
989✔
386
        obj
387
    end
388

389
    let rec arg_to_yojson_rec (arg : Graphql_parser.const_value) : Yojson.Safe.t
390
        =
391
      match arg with
4,145✔
392
      | `Null ->
×
393
          `Null
394
      | `Int x ->
×
395
          `Int x
396
      | `Float x ->
×
397
          `Float x
398
      | `String x ->
4,145✔
399
          `String x
400
      | `Bool x ->
×
401
          `Bool x
402
      | `Enum x ->
×
403
          `String x
404
      | `List x ->
×
405
          `List (List.map x ~f:arg_to_yojson_rec)
×
406
      | `Assoc x ->
×
407
          `Assoc
408
            (List.map x ~f:(fun (key, value) -> (key, arg_to_yojson_rec value)))
×
409

410
    let arg_to_yojson arg : (Yojson.Safe.t, string) result =
411
      Ok (arg_to_yojson_rec arg)
4,145✔
412
  end
413
end
414

415
module Graphql_query = struct
416
  module Input = struct
417
    type 'a t = < graphql_query : string option ref ; .. > as 'a
418
  end
419

420
  module Accumulator = struct
421
    type 'a t =
422
      < graphql_query_accumulator : (string * string option) option list ref
423
      ; .. >
424
      as
425
      'a
426
      constraint 'a t = 'a Input.t
427
  end
428

429
  let add_field ~t_fields_annots :
430
      'a Input.t -> 'field -> 'obj -> 'creator * 'obj =
431
   fun t_field field acc_obj ->
2,852✔
432
    let annotations =
2,852✔
433
      Fields_derivers.Annotations.Fields.of_annots t_fields_annots
434
        (Field.name field)
2,852✔
435
    in
436
    let rest = !(acc_obj#graphql_query_accumulator) in
2,852✔
437
    acc_obj#graphql_query_accumulator :=
2,852✔
UNCOV
438
      ( if annotations.skip || !(t_field#skip) then None
×
439
      else
440
        Some
2,852✔
441
          ( Option.value annotations.name
2,852✔
442
              ~default:(Fields_derivers.name_under_to_camel field)
2,852✔
443
          , !(t_field#graphql_query) ) )
2,852✔
444
      :: rest ;
445
    ((fun _ -> failwith "unused"), acc_obj)
×
446

447
  let finish (_creator, obj) =
448
    let graphql_query_accumulator = !(obj#graphql_query_accumulator) in
805✔
449
    obj#graphql_query :=
805✔
450
      Some
451
        (sprintf "{\n%s\n}"
805✔
452
           ( List.filter_map graphql_query_accumulator
805✔
453
               ~f:
454
                 (Option.map ~f:(fun (k, v) ->
455
                      match v with None -> k | Some v -> sprintf "%s %s" k v )
713✔
456
                 )
457
           |> List.rev |> String.concat ~sep:"\n" ) ) ;
805✔
458
    obj
459

460
  let scalar obj =
461
    obj#graphql_query := None ;
2,346✔
462
    obj
463

464
  let skip obj = scalar obj
69✔
465

466
  let int obj = scalar obj
23✔
467

468
  let string obj = scalar obj
92✔
469

470
  let bool obj = scalar obj
253✔
471

472
  (* nullable and lists of things are projected to the inner thing ONLY IF inner
473
   * projectable. *)
474
  let wrapped x obj =
475
    obj#graphql_query := !(x#graphql_query) ;
2,047✔
476
    obj
477

478
  let option x obj = wrapped x obj
851✔
479

480
  let list x obj = wrapped x obj
207✔
481

482
  let inner_query obj = !(obj#graphql_query)
2✔
483
end
484

485
module IO = struct
486
  include Async_kernel.Deferred
487

UNCOV
488
  let bind x f = bind x ~f
×
489

490
  module Stream = struct
491
    type 'a t = 'a Async_kernel.Pipe.Reader.t
492

493
    let map t f =
494
      Async_kernel.Pipe.map' t ~f:(fun q ->
×
495
          Async_kernel.Deferred.Queue.map q ~f )
×
496

497
    let iter t f = Async_kernel.Pipe.iter t ~f
×
498

499
    let close = Async_kernel.Pipe.close_read
500
  end
501
end
502

503
module Field_error = struct
504
  type t = string
505

506
  let message_of_field_error t = t
×
507

508
  let extensions_of_field_error _t = None
×
509
end
510

511
module Schema = Graphql_schema.Make (IO) (Field_error)
512
module Graphql = Graphql_raw.Make (Schema)
513

514
module Test = struct
515
  let parse_query str =
UNCOV
516
    match Graphql_parser.parse str with
×
UNCOV
517
    | Ok res ->
×
518
        res
519
    | Error err ->
×
520
        failwith err
521

522
  let introspection_query () =
UNCOV
523
    parse_query Fields_derivers.introspection_query_raw
×
524
end
525

526
let%test_module "Test" =
527
  ( module struct
528
    (* Pure -- just like Graphql libraries functor application *)
529
    module IO = struct
530
      type +'a t = 'a
531

UNCOV
532
      let bind t f = f t
×
533

UNCOV
534
      let return t = t
×
535

536
      module Stream = struct
537
        type 'a t = 'a Seq.t
538

539
        let map t f = Seq.map f t
×
540

541
        let iter t f = Seq.iter f t
×
542

543
        let close _t = ()
×
544
      end
545
    end
546

547
    module Schema = Graphql_schema.Make (IO) (Field_error)
548
    module Graphql = Graphql_raw.Make (Schema)
549
    module Graphql_fields = Graphql.Fields
550
    module Graphql_args = Graphql.Args
551

552
    let deriver (type a b c d) () :
553
        < contramap : (a -> b) ref
554
        ; graphql_fields : c Graphql_fields.Input.T.t ref
555
        ; nullable_graphql_fields : d Graphql_fields.Input.T.t ref
556
        ; .. >
557
        as
558
        'row =
559
      (* We have to declare these outside of the object, otherwise the method
560
       * will create a new ref each time it is called. *)
UNCOV
561
      let open Graphql_fields in
×
562
      let graphql_fields =
563
        ref Input.T.{ run = (fun () -> failwith "unimplemented1") }
×
564
      in
565
      let graphql_arg = ref (fun () -> failwith "unimplemented2") in
×
566
      let contramap = ref (fun _ -> failwith "unimplemented3") in
×
567
      let map = ref (fun _ -> failwith "unimplemented4") in
×
568
      let nullable_graphql_fields =
569
        ref Input.T.{ run = (fun () -> failwith "unimplemented5") }
×
570
      in
571
      let nullable_graphql_arg = ref (fun () -> failwith "unimplemented6") in
×
572
      let graphql_fields_accumulator = ref [] in
573
      let graphql_arg_accumulator = ref Graphql_args.Acc.T.Init in
574
      let graphql_creator = ref (fun _ -> failwith "unimplemented7") in
×
575
      let graphql_query = ref None in
576
      let graphql_query_accumulator = ref [] in
577
      let skip = ref false in
578
      object
UNCOV
579
        method skip = skip
×
580

UNCOV
581
        method graphql_fields = graphql_fields
×
582

UNCOV
583
        method graphql_arg = graphql_arg
×
584

UNCOV
585
        method contramap = contramap
×
586

UNCOV
587
        method map = map
×
588

UNCOV
589
        method nullable_graphql_fields = nullable_graphql_fields
×
590

UNCOV
591
        method nullable_graphql_arg = nullable_graphql_arg
×
592

UNCOV
593
        method graphql_fields_accumulator = graphql_fields_accumulator
×
594

UNCOV
595
        method graphql_arg_accumulator = graphql_arg_accumulator
×
596

UNCOV
597
        method graphql_creator = graphql_creator
×
598

UNCOV
599
        method graphql_query = graphql_query
×
600

UNCOV
601
        method graphql_query_accumulator = graphql_query_accumulator
×
602
      end
603

UNCOV
604
    let o () = deriver ()
×
605

UNCOV
606
    let raw_server ?(print = false) q c =
×
UNCOV
607
      let schema = Schema.(schema [ q ] ~mutations:[] ~subscriptions:[]) in
×
608
      let res = Schema.execute schema () c in
UNCOV
609
      match res with
×
UNCOV
610
      | Ok (`Response data) ->
×
611
          if print then Yojson.Basic.pretty_print Format.std_formatter data ;
×
UNCOV
612
          data |> Yojson.Basic.to_string
×
613
      | Error err ->
×
614
          failwithf "Unexpected error: %s" (Yojson.Basic.to_string err) ()
×
615
      | _ ->
×
616
          failwith "Unexpected response"
617

618
    let query_schema typ v =
UNCOV
619
      Schema.(
×
UNCOV
620
        field "query" ~typ:(non_null typ)
×
621
          ~args:Arg.[]
622
          ~doc:"sample query"
UNCOV
623
          ~resolve:(fun _ _ -> v))
×
624

625
    let query_for_all typ v str =
UNCOV
626
      raw_server (query_schema typ v) (Test.parse_query str)
×
627

UNCOV
628
    let hit_server ?print q = raw_server ?print q (Test.introspection_query ())
×
629

630
    let hit_server_query (typ : _ Schema.typ) v =
UNCOV
631
      hit_server (query_schema typ v)
×
632

633
    let hit_server_args (arg_typ : 'a Schema.Arg.arg_typ) =
UNCOV
634
      hit_server
×
635
        Schema.(
UNCOV
636
          field "args" ~typ:(non_null int)
×
UNCOV
637
            ~args:Arg.[ arg "input" ~typ:arg_typ ]
×
638
            ~doc:"sample args query"
639
            ~resolve:(fun _ _ _ -> 0))
×
640

641
    module T1 = struct
642
      (** T1 is foo *)
UNCOV
643
      type t =
×
UNCOV
644
        { foo_hello : int option
×
645
        ; skipped : int [@skip]
×
UNCOV
646
        ; bar : string list [@name "bar1"]
×
647
        }
648
      [@@deriving annot, fields]
649

650
      let _v = { foo_hello = Some 1; skipped = 0; bar = [ "baz1"; "baz2" ] }
651

652
      let doc = "T1 is foo"
653

654
      let manual_typ =
655
        Schema.(
UNCOV
656
          obj "T1" ~doc ~fields:(fun _ ->
×
UNCOV
657
              [ field "fooHello"
×
658
                  ~args:Arg.[]
659
                  ~typ:int
660
                  ~resolve:(fun _ t -> t.foo_hello)
×
UNCOV
661
              ; field "bar1"
×
662
                  ~args:Arg.[]
UNCOV
663
                  ~typ:(non_null (list (non_null string)))
×
664
                  ~resolve:(fun _ t -> t.bar)
×
665
              ] ))
666

667
      let derived init =
UNCOV
668
        let open Graphql_fields in
×
UNCOV
669
        let ( !. ) x fd acc = add_field ~t_fields_annots (x (o ())) fd acc in
×
UNCOV
670
        Fields.make_creator init
×
UNCOV
671
          ~foo_hello:!.(option @@ int @@ o ())
×
UNCOV
672
          ~skipped:!.skip
×
UNCOV
673
          ~bar:!.(list @@ string @@ o ())
×
674
        |> finish "T1" ~t_toplevel_annots
675

676
      module Args = struct
677
        let manual_typ =
678
          Schema.Arg.(
UNCOV
679
            obj "T1Input" ~doc
×
680
              ~fields:
UNCOV
681
                [ arg "bar1" ~typ:(non_null (list (non_null string)))
×
UNCOV
682
                ; arg "fooHello" ~typ:int
×
683
                ]
684
              ~coerce:(fun bar foo_hello -> { bar; skipped = 0; foo_hello }))
×
685

686
        let derived init =
UNCOV
687
          let open Graphql_args in
×
688
          let ( !. ) ?skip_data x fd acc =
UNCOV
689
            add_field ?skip_data ~t_fields_annots (x (o ())) fd acc
×
690
          in
UNCOV
691
          Fields.make_creator init
×
UNCOV
692
            ~foo_hello:!.(option @@ int @@ o ())
×
UNCOV
693
            ~skipped:(( !. ) ~skip_data:0 skip)
×
UNCOV
694
            ~bar:!.(list @@ string @@ o ())
×
695
          |> finish "T1" ~t_toplevel_annots
696
      end
697

698
      module Query = struct
699
        let derived init =
UNCOV
700
          let open Graphql_query in
×
UNCOV
701
          let ( !. ) x fd acc = add_field ~t_fields_annots (x (o ())) fd acc in
×
UNCOV
702
          Fields.make_creator init
×
UNCOV
703
            ~foo_hello:!.(option @@ int @@ o ())
×
UNCOV
704
            ~skipped:!.skip
×
UNCOV
705
            ~bar:!.(list @@ string @@ o ())
×
706
          |> finish
707
      end
708
    end
709

710
    module Or_ignore_test = struct
711
      type 'a t = Check of 'a | Ignore
712

713
      let of_option = function None -> Ignore | Some x -> Check x
×
714

715
      let to_option = function Ignore -> None | Check x -> Some x
×
716

717
      let derived (x : ('input_type, 'b, 'c, _) Graphql_fields.Input.t) init :
718
          (_, _, 'c t, _) Graphql_fields.Input.t =
UNCOV
719
        let open Graphql_fields in
×
UNCOV
720
        let opt = option x (o ()) in
×
UNCOV
721
        contramap ~f:to_option opt init
×
722

723
      module Args = struct
724
        let derived (x : ('row1, 'c, 'input_type, _) Graphql_args.Input.t) init
725
            : ('row2, 'c t, 'input_type option, _) Graphql_args.Input.t =
UNCOV
726
          let open Graphql_args in
×
UNCOV
727
          let opt = option x (o ()) in
×
UNCOV
728
          map ~f:of_option opt init
×
729
      end
730

731
      module Query = struct
732
        let derived x init =
UNCOV
733
          let open Graphql_query in
×
734
          option x init
735
      end
736
    end
737

738
    module T2 = struct
UNCOV
739
      type t = { foo : T1.t Or_ignore_test.t } [@@deriving annot, fields]
×
740

741
      let v1 =
742
        { foo =
743
            Check
744
              { T1.foo_hello = Some 1; skipped = 0; bar = [ "baz1"; "baz2" ] }
745
        }
746

747
      let v2 = { foo = Ignore }
748

749
      let manual_typ =
750
        Schema.(
UNCOV
751
          obj "T2" ?doc:None ~fields:(fun _ ->
×
UNCOV
752
              [ field "foo"
×
753
                  ~args:Arg.[]
754
                  ~typ:T1.manual_typ
755
                  ~resolve:(fun _ t -> Or_ignore_test.to_option t.foo)
×
756
              ] ))
757

758
      let derived init =
UNCOV
759
        let open Graphql_fields in
×
UNCOV
760
        let ( !. ) x fd acc = add_field ~t_fields_annots (x (o ())) fd acc in
×
UNCOV
761
        Fields.make_creator init
×
UNCOV
762
          ~foo:!.(Or_ignore_test.derived @@ T1.derived @@ o ())
×
763
        |> finish "T2" ~t_toplevel_annots
764

765
      module Args = struct
766
        let manual_typ =
767
          Schema.Arg.(
UNCOV
768
            obj "T2Input" ?doc:None
×
UNCOV
769
              ~fields:[ arg "foo" ~typ:T1.Args.manual_typ ]
×
770
              ~coerce:(fun foo -> Or_ignore_test.of_option foo))
×
771

772
        let derived init =
UNCOV
773
          let open Graphql_args in
×
UNCOV
774
          let ( !. ) x fd acc = add_field ~t_fields_annots (x (o ())) fd acc in
×
UNCOV
775
          Fields.make_creator init
×
UNCOV
776
            ~foo:!.(Or_ignore_test.Args.derived @@ T1.Args.derived @@ o ())
×
777
          |> finish "T2" ~t_toplevel_annots
778
      end
779

780
      module Query = struct
781
        let manual =
782
          {|
783
            {
784
              foo {
785
                fooHello
786
                bar1
787
              }
788
            }
789
          |}
790

791
        let derived init =
UNCOV
792
          let open Graphql_query in
×
UNCOV
793
          let ( !. ) x fd acc = add_field ~t_fields_annots (x (o ())) fd acc in
×
UNCOV
794
          Fields.make_creator init
×
UNCOV
795
            ~foo:!.(Or_ignore_test.Query.derived @@ T1.Query.derived @@ o ())
×
796
          |> finish
797
      end
798
    end
799

800
    let%test_unit "T2 fold" =
UNCOV
801
      let open Graphql_fields in
×
802
      let generated_typ =
UNCOV
803
        let typ_input = T2.(option @@ derived @@ o ()) (o ()) in
×
UNCOV
804
        !(typ_input#graphql_fields).run ()
×
805
      in
UNCOV
806
      [%test_eq: string]
×
UNCOV
807
        (hit_server_query generated_typ T2.v1)
×
UNCOV
808
        (hit_server_query T2.manual_typ T2.v1) ;
×
UNCOV
809
      [%test_eq: string]
×
UNCOV
810
        (hit_server_query generated_typ T2.v2)
×
UNCOV
811
        (hit_server_query T2.manual_typ T2.v2)
×
812

813
    let%test_unit "T2 unfold" =
UNCOV
814
      let open Graphql_args in
×
815
      let generated_arg_typ =
UNCOV
816
        let obj = T2.(option @@ Args.derived @@ o ()) (o ()) in
×
UNCOV
817
        !(obj#graphql_arg) ()
×
818
      in
UNCOV
819
      [%test_eq: string]
×
UNCOV
820
        (hit_server_args generated_arg_typ)
×
UNCOV
821
        (hit_server_args T2.Args.manual_typ)
×
822

823
    let%test_unit "T2 query expected & parses" =
UNCOV
824
      let open Graphql_fields in
×
825
      let generated_typ =
UNCOV
826
        let typ_input = T2.(option @@ derived @@ o ()) (o ()) in
×
UNCOV
827
        !(typ_input#graphql_fields).run ()
×
828
      in
829
      let open Graphql_query in
830
      let generated_query =
UNCOV
831
        T2.Query.(option @@ derived @@ o ()) (o ())
×
UNCOV
832
        |> inner_query |> Option.value_exn
×
833
      in
UNCOV
834
      let prefix = "query TestQuery { query" in
×
835
      let suffix = "}" in
UNCOV
836
      [%test_eq: string]
×
UNCOV
837
        (query_for_all generated_typ T2.v1 (prefix ^ generated_query ^ suffix))
×
UNCOV
838
        (query_for_all generated_typ T2.v1 (prefix ^ T2.Query.manual ^ suffix))
×
839
  end )
42✔
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