1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 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.directives
21 
22 import cats.Monad
23 import akka.http.scaladsl.model.StatusCodes
24 import akka.http.scaladsl.server._
25 import org.make.core.{ValidationError, ValidationFailedError}
26 
27 import scala.concurrent.Future
28 import scala.util.{Failure, Success}
29 
30 object FutureDirectivesExtensions extends Directives {
31 
32   implicit class FutureWithRoutes[T](f: Future[T]) {
33 
34     def asDirective: Directive1[T] =
35       extract(_ => f).flatMap { fa =>
36         onComplete(fa).flatMap {
37           case Success(value) => provide(value)
38           case Failure(e)     => failWith(e)
39         }
40       }
41   }
42 
43   implicit class FutureOptionWithRoutes[T](f: Future[Option[T]]) {
44 
45     def asDirectiveOrNotFound: Directive1[T] =
46       f.asDirective.flatMap {
47         case Some(value) => provide(value)
48         case None        => complete(StatusCodes.NotFound)
49       }
50 
51     def asDirectiveOrBadRequest(err: ValidationError): Directive1[T] =
52       f.asDirective.flatMap {
53         case Some(value) => provide(value)
54         case None        => failWith(ValidationFailedError(Seq(err)))
55       }
56   }
57 
58   implicit val directive1Monad: Monad[Directive1] = new Monad[Directive1] {
59 
60     override def pure[A](x: A): Directive1[A] = provide(x)
61 
62     override def flatMap[A, B](fa: Directive1[A])(f: A => Directive1[B]): Directive1[B] =
63       fa.flatMap(f)
64 
65     // This method implementation isn't actually tail-recursive because we were unable to make it
66     // so. That completely ruins the point of this method even existing, but it is required, and we
67     // figured a flawed implementation would be better than no implementation (`???`).
68     @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
69     override def tailRecM[A, B](a: A)(f: A => Directive1[Either[A, B]]): Directive1[B] = {
70       f(a).flatMap {
71         _.fold(tailRecM(_)(f), pure)
72       }
73     }
74   }
75 }
Line Stmt Id Pos Tree Symbol Tests Code
35 36918 1194 - 1194 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 org.make.api.technical.directives.clientdirectivestest util.this.Tuple.forTuple1[T]
35 48871 1170 - 1185 Apply akka.http.scaladsl.server.directives.BasicDirectives.extract org.make.api.technical.directives.clientdirectivestest FutureDirectivesExtensions.this.extract[scala.concurrent.Future[T]](((x$1: akka.http.scaladsl.server.RequestContext) => FutureWithRoutes.this.f))
35 49941 1170 - 1345 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap org.make.api.technical.directives.clientdirectivestest server.this.Directive.SingleValueTransformers[scala.concurrent.Future[T]](FutureDirectivesExtensions.this.extract[scala.concurrent.Future[T]](((x$1: akka.http.scaladsl.server.RequestContext) => FutureWithRoutes.this.f))).flatMap[(T,)](((fa: scala.concurrent.Future[T]) => server.this.Directive.SingleValueTransformers[scala.util.Try[T]](FutureDirectivesExtensions.this.onComplete[T](fa)).flatMap[(T,)](((x0$1: scala.util.Try[T]) => x0$1 match { case (value: T): scala.util.Success[T]((value @ _)) => FutureDirectivesExtensions.this.provide[T](value) case (exception: Throwable): scala.util.Failure[T]((e @ _)) => server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.failWith(e))(util.this.Tuple.forTuple1[T]) }))(util.this.Tuple.forTuple1[T])))(util.this.Tuple.forTuple1[T])
35 36883 1183 - 1184 Select org.make.api.technical.directives.FutureDirectivesExtensions.FutureWithRoutes.f org.make.api.technical.directives.clientdirectivestest FutureWithRoutes.this.f
36 43719 1210 - 1337 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap org.make.api.technical.directives.clientdirectivestest server.this.Directive.SingleValueTransformers[scala.util.Try[T]](FutureDirectivesExtensions.this.onComplete[T](fa)).flatMap[(T,)](((x0$1: scala.util.Try[T]) => x0$1 match { case (value: T): scala.util.Success[T]((value @ _)) => FutureDirectivesExtensions.this.provide[T](value) case (exception: Throwable): scala.util.Failure[T]((e @ _)) => server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.failWith(e))(util.this.Tuple.forTuple1[T]) }))(util.this.Tuple.forTuple1[T])
36 45471 1210 - 1224 Apply akka.http.scaladsl.server.directives.FutureDirectives.onComplete org.make.api.technical.directives.clientdirectivestest FutureDirectivesExtensions.this.onComplete[T](fa)
36 31092 1233 - 1233 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 org.make.api.technical.directives.clientdirectivestest util.this.Tuple.forTuple1[T]
37 37192 1268 - 1282 Apply akka.http.scaladsl.server.directives.BasicDirectives.provide org.make.api.technical.directives.clientdirectivestest FutureDirectivesExtensions.this.provide[T](value)
38 51269 1316 - 1327 Apply akka.http.scaladsl.server.directives.RouteDirectives.failWith FutureDirectivesExtensions.this.failWith(e)
38 43403 1324 - 1324 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 util.this.Tuple.forTuple1[T]
38 38983 1316 - 1327 ApplyToImplicitArgs akka.http.scaladsl.server.StandardRoute.toDirective server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.failWith(e))(util.this.Tuple.forTuple1[T])
46 37932 1472 - 1485 Select org.make.api.technical.directives.FutureDirectivesExtensions.FutureWithRoutes.asDirective FutureDirectivesExtensions.this.FutureWithRoutes[Option[T]](FutureOptionWithRoutes.this.f).asDirective
46 45258 1494 - 1494 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 util.this.Tuple.forTuple1[T]
46 37688 1472 - 1605 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap server.this.Directive.SingleValueTransformers[Option[T]](FutureDirectivesExtensions.this.FutureWithRoutes[Option[T]](FutureOptionWithRoutes.this.f).asDirective).flatMap[(T,)](((x0$1: Option[T]) => x0$1 match { case (value: T): Some[T]((value @ _)) => FutureDirectivesExtensions.this.provide[T](value) case scala.None => server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.complete(marshalling.this.ToResponseMarshallable.apply[akka.http.scaladsl.model.StatusCodes.ClientError](akka.http.scaladsl.model.StatusCodes.NotFound)(marshalling.this.Marshaller.fromStatusCode)))(util.this.Tuple.forTuple1[T]) }))(util.this.Tuple.forTuple1[T])
46 45511 1472 - 1473 Select org.make.api.technical.directives.FutureDirectivesExtensions.FutureOptionWithRoutes.f FutureOptionWithRoutes.this.f
47 51026 1524 - 1538 Apply akka.http.scaladsl.server.directives.BasicDirectives.provide FutureDirectivesExtensions.this.provide[T](value)
48 43925 1567 - 1597 Apply akka.http.scaladsl.server.directives.RouteDirectives.complete FutureDirectivesExtensions.this.complete(marshalling.this.ToResponseMarshallable.apply[akka.http.scaladsl.model.StatusCodes.ClientError](akka.http.scaladsl.model.StatusCodes.NotFound)(marshalling.this.Marshaller.fromStatusCode))
48 35036 1588 - 1588 Select akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers.fromStatusCode marshalling.this.Marshaller.fromStatusCode
48 49974 1567 - 1597 ApplyToImplicitArgs akka.http.scaladsl.server.StandardRoute.toDirective server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.complete(marshalling.this.ToResponseMarshallable.apply[akka.http.scaladsl.model.StatusCodes.ClientError](akka.http.scaladsl.model.StatusCodes.NotFound)(marshalling.this.Marshaller.fromStatusCode)))(util.this.Tuple.forTuple1[T])
48 43442 1576 - 1596 Select akka.http.scaladsl.model.StatusCodes.NotFound akka.http.scaladsl.model.StatusCodes.NotFound
48 36683 1575 - 1575 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 util.this.Tuple.forTuple1[T]
48 31132 1576 - 1596 ApplyToImplicitArgs akka.http.scaladsl.marshalling.ToResponseMarshallable.apply marshalling.this.ToResponseMarshallable.apply[akka.http.scaladsl.model.StatusCodes.ClientError](akka.http.scaladsl.model.StatusCodes.NotFound)(marshalling.this.Marshaller.fromStatusCode)
52 37184 1706 - 1706 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 org.make.api.technical.tracking.trackingapitest util.this.Tuple.forTuple1[T]
52 50216 1684 - 1828 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap org.make.api.technical.tracking.trackingapitest server.this.Directive.SingleValueTransformers[Option[T]](FutureDirectivesExtensions.this.FutureWithRoutes[Option[T]](FutureOptionWithRoutes.this.f).asDirective).flatMap[(T,)](((x0$1: Option[T]) => x0$1 match { case (value: T): Some[T]((value @ _)) => FutureDirectivesExtensions.this.provide[T](value) case scala.None => server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.failWith(org.make.core.ValidationFailedError.apply(scala.`package`.Seq.apply[org.make.core.ValidationError](err))))(util.this.Tuple.forTuple1[T]) }))(util.this.Tuple.forTuple1[T])
52 50464 1684 - 1685 Select org.make.api.technical.directives.FutureDirectivesExtensions.FutureOptionWithRoutes.f org.make.api.technical.tracking.trackingapitest FutureOptionWithRoutes.this.f
52 43197 1684 - 1697 Select org.make.api.technical.directives.FutureDirectivesExtensions.FutureWithRoutes.asDirective org.make.api.technical.tracking.trackingapitest FutureDirectivesExtensions.this.FutureWithRoutes[Option[T]](FutureOptionWithRoutes.this.f).asDirective
53 35072 1736 - 1750 Apply akka.http.scaladsl.server.directives.BasicDirectives.provide org.make.api.technical.tracking.trackingapitest FutureDirectivesExtensions.this.provide[T](value)
54 43674 1788 - 1819 Apply org.make.core.ValidationFailedError.apply org.make.api.technical.tracking.trackingapitest org.make.core.ValidationFailedError.apply(scala.`package`.Seq.apply[org.make.core.ValidationError](err))
54 49179 1787 - 1787 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 org.make.api.technical.tracking.trackingapitest util.this.Tuple.forTuple1[T]
54 45297 1779 - 1820 ApplyToImplicitArgs akka.http.scaladsl.server.StandardRoute.toDirective org.make.api.technical.tracking.trackingapitest server.this.StandardRoute.toDirective[(T,)](FutureDirectivesExtensions.this.failWith(org.make.core.ValidationFailedError.apply(scala.`package`.Seq.apply[org.make.core.ValidationError](err))))(util.this.Tuple.forTuple1[T])
54 31169 1810 - 1818 Apply scala.collection.SeqFactory.Delegate.apply org.make.api.technical.tracking.trackingapitest scala.`package`.Seq.apply[org.make.core.ValidationError](err)
54 36112 1779 - 1820 Apply akka.http.scaladsl.server.directives.RouteDirectives.failWith org.make.api.technical.tracking.trackingapitest FutureDirectivesExtensions.this.failWith(org.make.core.ValidationFailedError.apply(scala.`package`.Seq.apply[org.make.core.ValidationError](err)))
58 43156 1886 - 1889 Apply org.make.api.technical.directives.FutureDirectivesExtensions.$anon.<init> org.make.api.technical.directives.clientdirectivestest new $anon()
60 42631 1959 - 1969 Apply akka.http.scaladsl.server.directives.BasicDirectives.provide FutureDirectivesExtensions.this.provide[A](x)
63 34829 2077 - 2077 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 util.this.Tuple.forTuple1[B]
63 30920 2067 - 2080 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap server.this.Directive.SingleValueTransformers[A](fa).flatMap[(B,)](f)(util.this.Tuple.forTuple1[B])
70 38248 2541 - 2541 TypeApply akka.http.scaladsl.server.util.Tuple.forTuple1 util.this.Tuple.forTuple1[B]
70 50255 2528 - 2587 ApplyToImplicitArgs akka.http.scaladsl.server.Directive.SingleValueTransformers.flatMap server.this.Directive.SingleValueTransformers[Either[A,B]](f.apply(a)).flatMap[(B,)](((x$2: Either[A,B]) => x$2.fold[akka.http.scaladsl.server.Directive1[B]](((x$3: A) => $anon.this.tailRecM[A, B](x$3)(f)), ((x: B) => $anon.this.pure[B](x)))))(util.this.Tuple.forTuple1[B])
70 43711 2528 - 2532 Apply scala.Function1.apply f.apply(a)
71 49929 2574 - 2578 Apply org.make.api.technical.directives.FutureDirectivesExtensions.$anon.pure $anon.this.pure[B](x)
71 41645 2551 - 2579 Apply scala.util.Either.fold x$2.fold[akka.http.scaladsl.server.Directive1[B]](((x$3: A) => $anon.this.tailRecM[A, B](x$3)(f)), ((x: B) => $anon.this.pure[B](x)))
71 35869 2558 - 2572 Apply org.make.api.technical.directives.FutureDirectivesExtensions.$anon.tailRecM $anon.this.tailRecM[A, B](x$3)(f)