diff --git a/examples/src/main/resources/gateway_v2/gateway.js b/examples/src/main/resources/gateway_v2/gateway.js index c067328197..d06a42c1a3 100644 --- a/examples/src/main/resources/gateway_v2/gateway.js +++ b/examples/src/main/resources/gateway_v2/gateway.js @@ -1,6 +1,7 @@ -const {ApolloServer} = require('apollo-server'); -const {ApolloServerPluginInlineTrace} = require('apollo-server-core') -const {ApolloGateway, IntrospectAndCompose} = require('@apollo/gateway'); +import { ApolloServer } from '@apollo/server'; +import { ApolloServerPluginInlineTrace } from '@apollo/server/plugin/inlineTrace' +import { ApolloGateway, IntrospectAndCompose } from '@apollo/gateway'; +import {startStandaloneServer} from "@apollo/server/standalone"; const gateway = new ApolloGateway({ supergraphSdl: new IntrospectAndCompose({ @@ -21,7 +22,9 @@ const gateway = new ApolloGateway({ ] }); - server.listen().then(({url}) => { - console.log(`🚀 Server ready at ${url}`) + const { url } = await startStandaloneServer(server, { + listen: { port: 4000 } }) + + console.log(`🚀 Server ready at ${url}`) })(); \ No newline at end of file diff --git a/examples/src/main/resources/gateway_v2/package.json b/examples/src/main/resources/gateway_v2/package.json index e5547488db..df5a301aa2 100644 --- a/examples/src/main/resources/gateway_v2/package.json +++ b/examples/src/main/resources/gateway_v2/package.json @@ -2,6 +2,7 @@ "name": "federated-gateway", "version": "1.0.0", "description": "", + "type": "module", "main": "gateway.js", "scripts": { "start": "node gateway.js" @@ -9,8 +10,8 @@ "keywords": [], "license": "MIT", "dependencies": { - "apollo-server": "3.6.7", - "@apollo/gateway": "2.0.1", - "graphql": "16.3.0" + "@apollo/server": "4.9.5", + "@apollo/gateway": "2.6.2", + "graphql": "16.8.1" } } diff --git a/examples/src/main/scala/example/federation/FederatedApp.scala b/examples/src/main/scala/example/federation/FederatedApp.scala index ead7bf9662..8e3002110f 100644 --- a/examples/src/main/scala/example/federation/FederatedApp.scala +++ b/examples/src/main/scala/example/federation/FederatedApp.scala @@ -1,75 +1,19 @@ package example.federation +import caliban.quick._ import example.federation.FederationData.characters.sampleCharacters import example.federation.FederationData.episodes.sampleEpisodes -import caliban.Http4sAdapter -import caliban.interop.tapir.HttpInterpreter -import cats.data.Kleisli -import com.comcast.ip4s._ -import fs2.io.net.Network -import org.http4s.StaticFile -import org.http4s.implicits._ -import org.http4s.server.Router -import org.http4s.ember.server.EmberServerBuilder -import org.http4s.server.middleware.CORS import zio._ -import zio.interop.catz._ -object FederatedApp extends CatsApp { - import sttp.tapir.json.circe._ +object FederatedApp extends ZIOAppDefault { - type ExampleTask[A] = RIO[Any, A] - - private implicit val network: Network[ExampleTask] = Network.forAsync - - val service1 = - CharacterService - .make(sampleCharacters) - .memoize - .flatMap(layer => - for { - interpreter <- FederatedApi.Characters.api.interpreter.map(_.provideLayer(layer)) - _ <- EmberServerBuilder - .default[ExampleTask] - .withHost(host"localhost") - .withPort(port"8089") - .withHttpApp( - Router[ExampleTask]( - "/api/graphql" -> CORS.policy(Http4sAdapter.makeHttpService(HttpInterpreter(interpreter))), - "/graphiql" -> Kleisli.liftF(StaticFile.fromResource("/graphiql.html", None)) - ).orNotFound - ) - .build - .toScopedZIO - _ <- Console.printLine("Server online at http://localhost:8089/\nPress RETURN to stop...") - _ <- Console.readLine - } yield () - ) - - val service2 = - EpisodeService - .make(sampleEpisodes) - .memoize - .flatMap(layer => - for { - interpreter <- FederatedApi.Episodes.api.interpreter.map(_.provideLayer(layer)) - _ <- EmberServerBuilder - .default[ExampleTask] - .withHost(host"localhost") - .withPort(port"8088") - .withHttpApp( - Router[ExampleTask]( - "/api/graphql" -> CORS.policy(Http4sAdapter.makeHttpService(HttpInterpreter(interpreter))), - "/graphiql" -> Kleisli.liftF(StaticFile.fromResource("/graphiql.html", None)) - ).orNotFound - ) - .build - .toScopedZIO - _ <- Console.printLine("Server online at http://localhost:8088/\nPress RETURN to stop...") - _ <- Console.readLine - } yield () - ) + val episodesApi = FederatedApi.Episodes.api.runServer(8089, "/api/graphql", Some("/graphiql")) + val charactersApi = FederatedApi.Characters.api.runServer(8088, "/api/graphql", Some("/graphiql")) override def run = - (service1 race service2).exitCode + (episodesApi zipPar charactersApi) + .provide( + EpisodeService.make(sampleEpisodes), + CharacterService.make(sampleCharacters) + ) } diff --git a/examples/src/main/scala/example/federation/v2/FederatedApi.scala b/examples/src/main/scala/example/federation/v2/FederatedApi.scala index ee1e3f4228..bafdf0caf7 100644 --- a/examples/src/main/scala/example/federation/v2/FederatedApi.scala +++ b/examples/src/main/scala/example/federation/v2/FederatedApi.scala @@ -3,7 +3,7 @@ package example.federation.v2 import caliban._ import caliban.federation.EntityResolver import caliban.federation.tracing.ApolloFederatedTracing -import caliban.federation.v2_0.{ federated, GQLKey } +import caliban.federation.v2_6.{ federated, GQLKey } import caliban.schema.Annotations.{ GQLDeprecated, GQLDescription } import caliban.schema.{ ArgBuilder, GenericSchema, Schema } import caliban.schema.ArgBuilder.auto._ diff --git a/examples/src/main/scala/example/federation/v2/FederationData.scala b/examples/src/main/scala/example/federation/v2/FederationData.scala index 4f195649a2..f30a323a48 100644 --- a/examples/src/main/scala/example/federation/v2/FederationData.scala +++ b/examples/src/main/scala/example/federation/v2/FederationData.scala @@ -1,6 +1,6 @@ package example.federation.v2 -import caliban.federation.v2_0._ +import caliban.federation.v2_6._ import zio.query.ZQuery object FederationData { diff --git a/federation/src/main/scala/caliban/federation/FederationSupport.scala b/federation/src/main/scala/caliban/federation/FederationSupport.scala index 68f01e55bc..5eef75a02c 100644 --- a/federation/src/main/scala/caliban/federation/FederationSupport.scala +++ b/federation/src/main/scala/caliban/federation/FederationSupport.scala @@ -76,11 +76,10 @@ abstract class FederationSupport( * @param value a value of type `T` */ override def resolve(value: _Entity): Step[R] = - QueryStep( - _entityMap - .get(value.__typename) - .fold[ZQuery[R, CalibanError, Step[R]]](ZQuery.succeed(Step.NullStep))(_.resolve(value.value)) - ) + _entityMap + .get(value.__typename) + .fold[Step[R]](Step.NullStep)(resolver => QueryStep(resolver.resolve(value.value))) + } case class Query( diff --git a/federation/src/main/scala/caliban/federation/package.scala b/federation/src/main/scala/caliban/federation/package.scala index 60d8584e8e..d7405ad79c 100644 --- a/federation/src/main/scala/caliban/federation/package.scala +++ b/federation/src/main/scala/caliban/federation/package.scala @@ -1,6 +1,12 @@ package caliban -import caliban.federation.v2x.{ FederationDirectivesV2_3, FederationDirectivesV2_5, FederationV2, Versions } +import caliban.federation.v2x.{ + FederationDirectivesV2_3, + FederationDirectivesV2_5, + FederationDirectivesV2_6, + FederationV2, + Versions +} package object federation { @@ -10,5 +16,6 @@ package object federation { lazy val v2_3 = new FederationV2(List(Versions.v2_3)) with FederationDirectivesV2_3 lazy val v2_4 = new FederationV2(List(Versions.v2_4)) with FederationDirectivesV2_3 lazy val v2_5 = new FederationV2(List(Versions.v2_5)) with FederationDirectivesV2_5 + lazy val v2_6 = new FederationV2(List(Versions.v2_6)) with FederationDirectivesV2_6 } diff --git a/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_6.scala b/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_6.scala new file mode 100644 index 0000000000..4fa2eb3d08 --- /dev/null +++ b/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_6.scala @@ -0,0 +1,15 @@ +package caliban.federation.v2x + +import caliban.InputValue.ListValue +import caliban.Value.StringValue +import caliban.parsing.adt.Directive +import caliban.schema.Annotations.GQLDirective + +trait FederationDirectivesV2_6 extends FederationDirectivesV2_5 { + + def Policy(policies: List[List[String]]) = + Directive("policy", Map("policies" -> ListValue(policies.map(s => ListValue(s.map(s => StringValue(s))))))) + + case class GQLPolicy(policies: List[List[String]]) extends GQLDirective(Policy(policies)) + +} diff --git a/federation/src/main/scala/caliban/federation/v2x/FederationV2.scala b/federation/src/main/scala/caliban/federation/v2x/FederationV2.scala index dd137f5dc6..8716756b79 100644 --- a/federation/src/main/scala/caliban/federation/v2x/FederationV2.scala +++ b/federation/src/main/scala/caliban/federation/v2x/FederationV2.scala @@ -47,4 +47,9 @@ object FederationV2 { `import` = v2_4.`import` :+ Import("@authenticated") :+ Import("@requiresScopes") ) + private[v2x] val v2_6 = Link( + url = s"$federationV2Url/v2.6", + `import` = v2_5.`import` :+ Import("@policy") + ) + } diff --git a/federation/src/main/scala/caliban/federation/v2x/Versions.scala b/federation/src/main/scala/caliban/federation/v2x/Versions.scala index caaf74c73d..4e01494b35 100644 --- a/federation/src/main/scala/caliban/federation/v2x/Versions.scala +++ b/federation/src/main/scala/caliban/federation/v2x/Versions.scala @@ -7,5 +7,6 @@ object Versions { val v2_3 = FederationV2.v2_3 val v2_4 = FederationV2.v2_4 val v2_5 = FederationV2.v2_5 + val v2_6 = FederationV2.v2_6 }