1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2020 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical.graphql
21 
22 import java.io.IOException
23 
24 import caliban.CalibanError.ExecutionError
25 import caliban.InputValue
26 import caliban.Value.{EnumValue, StringValue => CalibanString}
27 import caliban.introspection.adt.{__EnumValue, __Type, __TypeKind}
28 import caliban.schema.{ArgBuilder, PureStep, Schema, Step}
29 import caliban._
30 import caliban.CalibanError._
31 import caliban.wrappers.Wrapper.OverallWrapper
32 import grizzled.slf4j.Logging
33 import enumeratum.values.{NoSuchMember, StringEnum, StringEnumEntry, ValueEnumEntry}
34 import org.make.core.StringValue
35 import zio.console.Console
36 import zio.query.Request
37 import zio.{IO, UIO, ULayer, ZIO, ZLayer}
38 
39 object GraphQLUtils extends Logging {
40 
41   val debugPrint: OverallWrapper[Console] =
42     new OverallWrapper[Console] {
43       def wrap[R <: Console](
44         process: GraphQLRequest => ZIO[R, Nothing, GraphQLResponse[CalibanError]]
45       ): GraphQLRequest => ZIO[R, Nothing, GraphQLResponse[CalibanError]] =
46         (request: GraphQLRequest) => IO.effectTotal(logger.debug(request.toString)) *> process(request)
47     }
48 
49   object ConsoleLoggingService {
50     val live: ULayer[Console] =
51       ZLayer.succeed(new Console.Service {
52         override def putStr(line: String): UIO[Unit] =
53           IO.succeed(logger.info(line))
54 
55         override def putStrErr(line: String): UIO[Unit] =
56           IO.succeed(logger.error(line))
57 
58         override def putStrLn(line: String): UIO[Unit] =
59           IO.succeed(logger.info(line))
60 
61         override def putStrLnErr(line: String): UIO[Unit] =
62           IO.succeed(logger.error(line))
63 
64         override val getStrLn: IO[IOException, String] =
65           IO.fail(new IOException("not supported"))
66       })
67   }
68 
69   implicit def stringValueStringSchema[T <: StringValue]: Schema[Any, T] =
70     Schema.stringSchema.contramap(_.value)
71 
72   implicit def enumSchema[T <: StringEnumEntry](implicit helper: StringEnum[T]): Schema[Any, T] =
73     new Schema[Any, T] {
74       private def sanitizeName(name: String): String = {
75         if (name.endsWith("$")) {
76           name.dropRight(1).mkString
77         } else {
78           name
79         }
80       }
81 
82       override protected[this] def toType(isInput: Boolean, isSubscription: Boolean): __Type = __Type(
83         kind = __TypeKind.ENUM,
84         name = Some(sanitizeName(helper.getClass.getSimpleName)),
85         description = None,
86         fields = _      => None,
87         interfaces = () => None,
88         possibleTypes = None,
89         enumValues = _ =>
90           Some(
91             helper.values
92               .map(v => __EnumValue(name = v.value, description = None, isDeprecated = false, deprecationReason = None))
93               .toList
94           ),
95         inputFields = None,
96         ofType = None,
97         directives = None,
98         origin = None
99       )
100       override def resolve(value: T): Step[Any] = PureStep(EnumValue(value.value))
101 
102     }
103 
104   implicit def enumArgBuilder[T <: StringEnumEntry](implicit helper: StringEnum[T]): ArgBuilder[T] = {
105     def parseEnumValue(value: String): Either[ExecutionError, T] = {
106       val parsedValue: Either[NoSuchMember[String, ValueEnumEntry[String]], T] =
107         helper.withValueEither(value)
108 
109       parsedValue.left.map { e =>
110         ExecutionError(s"${e.notFoundValue} is not a valid value, use ${e.enumValues.mkString(", ")}")
111       }
112     }
113 
114     (input: InputValue) => {
115       input match {
116         case EnumValue(value)     => parseEnumValue(value)
117         case CalibanString(value) => parseEnumValue(value)
118         case other                => Left(ExecutionError(s"cannot parse $other"))
119       }
120     }
121 
122   }
123 
124 }
125 
126 trait IdsRequest[F[_], T <: StringValue, U] extends Request[Throwable, F[U]] {
127   val ids: F[T]
128 }
Line Stmt Id Pos Tree Symbol Tests Code
42 37320 1495 - 1498 Apply org.make.api.technical.graphql.GraphQLUtils.$anon.<init> new $anon()
46 44099 1778 - 1794 Apply caliban.GraphQLRequest.toString request.toString()
46 37005 1765 - 1795 Apply grizzled.slf4j.Logger.debug GraphQLUtils.this.logger.debug(request.toString())
46 49002 1800 - 1816 Apply scala.Function1.apply process.apply(request)
46 45724 1750 - 1816 Apply zio.ZIO.*> zio.IO.effectTotal[Unit](GraphQLUtils.this.logger.debug(request.toString())).*>[R, Nothing, caliban.GraphQLResponse[caliban.CalibanError]](process.apply(request))
51 34682 1895 - 2445 ApplyToImplicitArgs zio.ZLayer.succeed zio.ZLayer.succeed[zio.console.Console.Service]({ final class $anon extends AnyRef with zio.console.Console.Service { def <init>(): <$anon: zio.console.Console.Service> = { $anon.super.<init>(); () }; override def putStr(line: String): zio.UIO[Unit] = zio.IO.succeed[Unit](GraphQLUtils.this.logger.info(line)); override def putStrErr(line: String): zio.UIO[Unit] = zio.IO.succeed[Unit](GraphQLUtils.this.logger.error(line)); override def putStrLn(line: String): zio.UIO[Unit] = zio.IO.succeed[Unit](GraphQLUtils.this.logger.info(line)); override def putStrLnErr(line: String): zio.UIO[Unit] = zio.IO.succeed[Unit](GraphQLUtils.this.logger.error(line)); private[this] val getStrLn: zio.IO[java.io.IOException,String] = zio.IO.fail[java.io.IOException](new java.io.IOException("not supported")); override <stable> <accessor> def getStrLn: zio.IO[java.io.IOException,String] = $anon.this.getStrLn }; new $anon() })((izumi.reflect.Tag.apply[zio.console.Console.Service](classOf[zio.console.package$$Console$Service], izumi.reflect.macrortti.LightTypeTag.parse[Nothing]((340388600: Int), ("\u0004\u0000\u0001\u001Bzio.console.Console.Service\u0001\u0002\u0003\u0000\u0000\u0013zio.console.Console\u0001\u0002\u0003\u0000\u0000\u0013zio.console.package\u0001\u0001": String), ("\u0000\u0001\u0004\u0000\u0001\u001Bzio.console.Console.Service\u0001\u0002\u0003\u0000\u0000\u0013zio.console.Console\u0001\u0002\u0003\u0000\u0000\u0013zio.console.package\u0001\u0001\u0001\u0004\u0000\u0001\u0014java.io.Serializable\u0001\u0001\u0001\u0000\u0001\u0090\u0002\u0001\u0002\u0003\u0000\u0000\u0090\u0003\u0001\u0002\u0003\u0000\u0000\u0090\u0004\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001": String), (11: Int))): izumi.reflect.Tag[zio.console.Console.Service]))
51 42266 1910 - 1913 Apply org.make.api.technical.graphql.GraphQLUtils.ConsoleLoggingService.$anon.<init> new $anon()
53 50636 2008 - 2025 Apply grizzled.slf4j.Logger.info GraphQLUtils.this.logger.info(line)
53 43529 1997 - 2026 Apply zio.IO.succeed zio.IO.succeed[Unit](GraphQLUtils.this.logger.info(line))
56 38342 2107 - 2125 Apply grizzled.slf4j.Logger.error GraphQLUtils.this.logger.error(line)
56 30790 2096 - 2126 Apply zio.IO.succeed zio.IO.succeed[Unit](GraphQLUtils.this.logger.error(line))
59 35737 2195 - 2224 Apply zio.IO.succeed zio.IO.succeed[Unit](GraphQLUtils.this.logger.info(line))
59 43854 2206 - 2223 Apply grizzled.slf4j.Logger.info GraphQLUtils.this.logger.info(line)
62 49035 2307 - 2325 Apply grizzled.slf4j.Logger.error GraphQLUtils.this.logger.error(line)
62 45637 2296 - 2326 Apply zio.IO.succeed zio.IO.succeed[Unit](GraphQLUtils.this.logger.error(line))
65 37358 2403 - 2435 Apply java.io.IOException.<init> new java.io.IOException("not supported")
65 50389 2395 - 2436 Apply zio.IO.fail zio.IO.fail[java.io.IOException](new java.io.IOException("not supported"))
70 43891 2530 - 2568 Apply caliban.schema.Schema.contramap caliban.schema.Schema.stringSchema.contramap[T](((x$1: T) => x$1.value))
70 31261 2560 - 2567 Select org.make.core.StringValue.value x$1.value
73 48786 2672 - 2675 Apply org.make.api.technical.graphql.GraphQLUtils.$anon.<init> new $anon()
75 35777 2762 - 2780 Apply java.lang.String.endsWith name.endsWith("$")
76 45681 2794 - 2820 Select scala.collection.StringOps.mkString scala.Predef.augmentString(scala.Predef.augmentString(name).dropRight(1)).mkString
76 37812 2794 - 2820 Block scala.collection.StringOps.mkString scala.Predef.augmentString(scala.Predef.augmentString(name).dropRight(1)).mkString
76 48798 2794 - 2811 Apply scala.collection.StringOps.dropRight scala.Predef.augmentString(name).dropRight(1)
78 51184 2848 - 2852 Ident org.make.api.technical.graphql.GraphQLUtils.$anon.name name
82 34993 2967 - 3528 Apply caliban.introspection.adt.__Type.apply caliban.introspection.adt.__Type.apply(caliban.introspection.adt.__TypeKind.ENUM, scala.Some.apply[String]($anon.this.sanitizeName(helper.getClass().getSimpleName())), scala.None, ((x$2: caliban.introspection.adt.__DeprecatedArgs) => scala.None), (() => scala.None), scala.None, ((x$3: caliban.introspection.adt.__DeprecatedArgs) => scala.Some.apply[List[caliban.introspection.adt.__EnumValue]](helper.values.map[caliban.introspection.adt.__EnumValue](((v: T) => caliban.introspection.adt.__EnumValue.apply(v.value, scala.None, false, scala.None))).toList)), scala.None, scala.None, scala.None, scala.None)
83 42304 2990 - 3005 Select caliban.introspection.adt.__TypeKind.ENUM caliban.introspection.adt.__TypeKind.ENUM
84 31307 3027 - 3070 Apply org.make.api.technical.graphql.GraphQLUtils.$anon.sanitizeName $anon.this.sanitizeName(helper.getClass().getSimpleName())
84 35200 3040 - 3069 Apply java.lang.Class.getSimpleName helper.getClass().getSimpleName()
84 44342 3022 - 3071 Apply scala.Some.apply scala.Some.apply[String]($anon.this.sanitizeName(helper.getClass().getSimpleName()))
85 36844 3095 - 3099 Select scala.None scala.None
86 48833 3128 - 3132 Select scala.None scala.None
87 45429 3161 - 3165 Select scala.None scala.None
88 37849 3191 - 3195 Select scala.None scala.None
90 49341 3233 - 3419 Apply scala.Some.apply scala.Some.apply[List[caliban.introspection.adt.__EnumValue]](helper.values.map[caliban.introspection.adt.__EnumValue](((v: T) => caliban.introspection.adt.__EnumValue.apply(v.value, scala.None, false, scala.None))).toList)
92 35238 3352 - 3357 Literal <nosymbol> false
92 43362 3331 - 3335 Select scala.None scala.None
92 43847 3289 - 3384 Apply caliban.introspection.adt.__EnumValue.apply caliban.introspection.adt.__EnumValue.apply(v.value, scala.None, false, scala.None)
92 31046 3379 - 3383 Select scala.None scala.None
92 50628 3308 - 3315 Select enumeratum.values.ValueEnumEntry.value v.value
93 36286 3251 - 3407 Select scala.collection.IterableOnceOps.toList helper.values.map[caliban.introspection.adt.__EnumValue](((v: T) => caliban.introspection.adt.__EnumValue.apply(v.value, scala.None, false, scala.None))).toList
95 41771 3443 - 3447 Select scala.None scala.None
96 37889 3466 - 3470 Select scala.None scala.None
97 50380 3493 - 3497 Select scala.None scala.None
98 42790 3516 - 3520 Select scala.None scala.None
100 43883 3588 - 3610 Apply caliban.Value.EnumValue.apply caliban.Value.EnumValue.apply(value.value)
100 31086 3598 - 3609 Select enumeratum.values.ValueEnumEntry.value value.value
100 36032 3579 - 3611 Apply caliban.schema.PureStep.apply caliban.schema.PureStep.apply(caliban.Value.EnumValue.apply(value.value))
107 41532 3881 - 3910 Apply enumeratum.values.ValueEnum.withValueEither helper.withValueEither(value)
109 43631 3918 - 4056 Apply scala.util.Either.LeftProjection.map parsedValue.left.map[caliban.CalibanError.ExecutionError](((e: enumeratum.values.NoSuchMember[String,enumeratum.values.ValueEnumEntry[String]]) => caliban.CalibanError.ExecutionError.apply(("".+(e.notFoundValue).+(" is not a valid value, use ").+(e.enumValues.mkString(", ")): String), caliban.CalibanError.ExecutionError.apply$default$2, caliban.CalibanError.ExecutionError.apply$default$3, caliban.CalibanError.ExecutionError.apply$default$4, caliban.CalibanError.ExecutionError.apply$default$5)))
110 37106 3954 - 3954 Select caliban.CalibanError.ExecutionError.apply$default$2 caliban.CalibanError.ExecutionError.apply$default$2
110 50417 3954 - 3954 Select caliban.CalibanError.ExecutionError.apply$default$3 caliban.CalibanError.ExecutionError.apply$default$3
110 34435 3954 - 3954 Select caliban.CalibanError.ExecutionError.apply$default$5 caliban.CalibanError.ExecutionError.apply$default$5
110 48338 3954 - 4048 Apply caliban.CalibanError.ExecutionError.apply caliban.CalibanError.ExecutionError.apply(("".+(e.notFoundValue).+(" is not a valid value, use ").+(e.enumValues.mkString(", ")): String), caliban.CalibanError.ExecutionError.apply$default$2, caliban.CalibanError.ExecutionError.apply$default$3, caliban.CalibanError.ExecutionError.apply$default$4, caliban.CalibanError.ExecutionError.apply$default$5)
110 43322 3954 - 3954 Select caliban.CalibanError.ExecutionError.apply$default$4 caliban.CalibanError.ExecutionError.apply$default$4
116 36073 4150 - 4171 Apply org.make.api.technical.graphql.GraphQLUtils.parseEnumValue parseEnumValue(value)
117 49845 4209 - 4230 Apply org.make.api.technical.graphql.GraphQLUtils.parseEnumValue parseEnumValue(value)
118 35492 4273 - 4311 Apply caliban.CalibanError.ExecutionError.apply caliban.CalibanError.ExecutionError.apply(("cannot parse ".+(other): String), caliban.CalibanError.ExecutionError.apply$default$2, caliban.CalibanError.ExecutionError.apply$default$3, caliban.CalibanError.ExecutionError.apply$default$4, caliban.CalibanError.ExecutionError.apply$default$5)
118 48258 4268 - 4312 Apply scala.util.Left.apply scala.`package`.Left.apply[caliban.CalibanError.ExecutionError, Nothing](caliban.CalibanError.ExecutionError.apply(("cannot parse ".+(other): String), caliban.CalibanError.ExecutionError.apply$default$2, caliban.CalibanError.ExecutionError.apply$default$3, caliban.CalibanError.ExecutionError.apply$default$4, caliban.CalibanError.ExecutionError.apply$default$5))
118 50172 4273 - 4273 Select caliban.CalibanError.ExecutionError.apply$default$4 caliban.CalibanError.ExecutionError.apply$default$4
118 43350 4273 - 4273 Select caliban.CalibanError.ExecutionError.apply$default$5 caliban.CalibanError.ExecutionError.apply$default$5
118 40966 4273 - 4273 Select caliban.CalibanError.ExecutionError.apply$default$2 caliban.CalibanError.ExecutionError.apply$default$2
118 37143 4273 - 4273 Select caliban.CalibanError.ExecutionError.apply$default$3 caliban.CalibanError.ExecutionError.apply$default$3