Skip to content

Commit

Permalink
add in support for apollo federation
Browse files Browse the repository at this point in the history
  • Loading branch information
fredex42 committed Jan 31, 2025
1 parent 2ae4ead commit d312aa7
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 5 deletions.
5 changes: 3 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ lazy val root = (project in file("."))
"org.http4s" %% "http4s-core" % "0.23.21",
"org.http4s" %% "http4s-dsl" % "0.23.21",
"org.http4s" %% "http4s-ember-server" % "0.23.21",
"org.sangria-graphql" %% "sangria" % "4.0.1",
"org.sangria-graphql" %% "sangria" % "4.1.1",
"org.sangria-graphql" %% "sangria-circe" % "1.3.2",
"io.circe" %% "circe-core" % "0.14.5",
"org.sangria-graphql" %% "sangria-federated" % "0.8.1",
"io.circe" %% "circe-core" % "0.14.9",
"io.circe" %% "circe-parser" % "0.14.5",
"io.circe" %% "circe-generic" % "0.14.5",
"io.circe" %% "circe-optics" % "0.14.1",
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/GraphQLServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class GraphQLServer(documentRepo:DocumentRepo) {
IO.fromFuture(
IO {
val context = GQLQueryContext(documentRepo, tier)
//FIXME - add in variables here
Executor.execute(inUseSchema, doc, middleware = permissions :: metrics :: Nil, userContext = context).map(_.asJson.noSpaces)
}
)
Expand Down
16 changes: 15 additions & 1 deletion src/main/scala/Main.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cats.effect._
import com.comcast.ip4s.{IpLiteralSyntax, Ipv4Address, Ipv6Address}
import datastore.ElasticsearchRepo
import datastore.{ElasticsearchRepo, GQLQueryContext}
import io.prometheus.client.hotspot.DefaultExports
import org.http4s._
import org.http4s.dsl.io._
Expand All @@ -10,6 +10,10 @@ import org.http4s.implicits._
import org.slf4j.LoggerFactory
import security.{ApiKeyAuth, DeveloperTier, InternalTier, Security, UserTier}
import internalmetrics.PrometheusMetrics
import io.circe.Json
import org.http4s.headers.Server
import sangria.federation.v2.Federation
import sangria.schema.Schema

import scala.concurrent.duration._
import utils.Config.fetchConfig
Expand Down Expand Up @@ -64,6 +68,11 @@ object Main extends IOApp {
}
}

// private def graphQL[F[_]: Async]: GraphQL[F, GQLQueryContext] = {
// val (schema, um) = Federation.federate[GQLQueryContext, Any, Json](
// Schema
// )
// }
def run(args:List[String]):IO[ExitCode] = {
val httpApp = Router("/" -> graphqlService).orNotFound
logger.info("Starting up on 0.0.0.0 port 9000")
Expand All @@ -77,5 +86,10 @@ object Main extends IOApp {
.build
.use(_=>IO.never)
.as(ExitCode.Success)
// Server.resource[IO, GQLQueryContext](
// logger,
// graphQL,
// port"9000"
// ).use()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import io.circe.generic.auto._
import io.circe.syntax._
import com.gu.contentapi.porter.model
import datastore.GQLQueryContext
import sangria.execution.deferred.HasId
import sangria.federation.v2.Directives
import sangria.macros.derive
import security.{InternalTier, RightsManagedTier}

Expand Down Expand Up @@ -163,6 +165,7 @@ object Content {
}
)
)
)
).withDirective(Directives.Key("id"))

implicit val ContentHasId:HasId[model.Content, String] = HasId(_.id)
}
25 changes: 24 additions & 1 deletion src/main/scala/com/gu/contentapi/porter/graphql/RootQuery.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import io.circe.Json

import scala.concurrent.ExecutionContext.Implicits.global
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder
import org.slf4j.LoggerFactory
import sangria.execution.deferred.Fetcher
import sangria.federation.v2.{Directives, EntityResolver, Federation}

import scala.concurrent.Future

Expand Down Expand Up @@ -128,5 +131,25 @@ object RootQuery {
)
)

val schema = Schema(Query)
//For graphQL Federeation
import com.gu.contentapi.porter.graphql.Content.ContentHasId
case class StateArg(id: String)
val articles: Fetcher[GQLQueryContext, Content, Content, String] = Fetcher {
(ctx, ids) => Future.sequence(
ids.map(id=>ctx.repo.docById(id).map(_.map(contentTransform))
.map(_.nodes.headOption))
).map(_.collect({case Some(content)=>content}))
}

implicit val decoder: sangria.federation.v2.Decoder[Json, StateArg] = deriveDecoder[StateArg].decodeJson(_)
private val articleStateResolver = EntityResolver[GQLQueryContext, Json, Content, StateArg](
__typeName = Content.getClass.getTypeName,
(arg, _) => articles.deferOpt(arg.id)
)

val (schema, um) = Federation.federate[GQLQueryContext, Unit, Json](
Schema(Query),
sangria.marshalling.circe.CirceInputUnmarshaller,
articleStateResolver
)
}

0 comments on commit d312aa7

Please sign in to comment.