Skip to content

Commit

Permalink
Merge pull request #567 from disneystreaming/change-service-encoding
Browse files Browse the repository at this point in the history
Move Op from parameter to member in smithy4s.Service
  • Loading branch information
Baccata authored Nov 9, 2022
2 parents f184289 + f23ff21 commit 4006e3d
Show file tree
Hide file tree
Showing 38 changed files with 241 additions and 240 deletions.
4 changes: 2 additions & 2 deletions modules/aws-http4s/src/smithy4s/aws/http4s/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import org.http4s.client.Client

package object http4s {

implicit final class ServiceOps[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _]](
private[this] val serviceProvider: smithy4s.Service.Provider[Alg, Op]
implicit final class ServiceOps[Alg[_[_, _, _, _, _]]](
private[this] val serviceProvider: smithy4s.Service.Provider[Alg]
) {

def awsClient[F[_]: Temporal](
Expand Down
29 changes: 14 additions & 15 deletions modules/aws/src/smithy4s/aws/AwsClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,18 @@ import cats.effect.Resource
import cats.syntax.all._

import internals.AwsJsonRPCInterpreter
import smithy4s.kinds.PolyFunction5

object AwsClient {

def apply[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _], F[_]: MonadThrow](
service: smithy4s.Service[Alg, Op],
def apply[Alg[_[_, _, _, _, _]], F[_]: MonadThrow](
service: smithy4s.Service[Alg],
awsEnv: AwsEnvironment[F]
): Resource[F, AwsClient[Alg, F]] =
prepare(service).map(_.interpret(awsEnv)).liftTo[Resource[F, *]]
prepare(service).map(_.build(awsEnv)).liftTo[Resource[F, *]]

def prepare[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _]](
service: smithy4s.Service[Alg, Op]
): Either[Throwable, AWSInterpreterBuilder[Alg, Op]] =
def prepare[Alg[_[_, _, _, _, _]]](
service: smithy4s.Service[Alg]
): Either[Throwable, AWSInterpreterBuilder[Alg]] =
for {
awsService <- service.hints
.get(_root_.aws.api.Service)
Expand All @@ -50,36 +49,36 @@ object AwsClient {
)
} yield new AWSInterpreterBuilder(awsProtocol, service, endpointPrefix)

final class AWSInterpreterBuilder[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _]](
final class AWSInterpreterBuilder[Alg[_[_, _, _, _, _]]](
awsProtocol: AwsProtocol,
service: smithy4s.Service[Alg, Op],
service: smithy4s.Service[Alg],
endpointPrefix: String
) {

def build[F[_]: MonadThrow](
private def interpreter[F[_]: MonadThrow](
awsEnv: AwsEnvironment[F]
): PolyFunction5[Op, AwsCall[F, *, *, *, *, *]] =
): service.Interpreter[AwsCall[F, *, *, *, *, *]] =
awsProtocol match {
case AwsProtocol.AWS_JSON_1_0(_) =>
new AwsJsonRPCInterpreter[Alg, Op, F](
new AwsJsonRPCInterpreter[Alg, service.Operation, F](
service,
endpointPrefix,
awsEnv,
"application/x-amz-json-1.0"
)

case AwsProtocol.AWS_JSON_1_1(_) =>
new AwsJsonRPCInterpreter[Alg, Op, F](
new AwsJsonRPCInterpreter[Alg, service.Operation, F](
service,
endpointPrefix,
awsEnv,
"application/x-amz-json-1.1"
)
}

def interpret[F[_]: MonadThrow](
def build[F[_]: MonadThrow](
awsEnv: AwsEnvironment[F]
): AwsClient[Alg, F] = service.fromPolyFunction(build(awsEnv))
): AwsClient[Alg, F] = service.fromPolyFunction(interpreter(awsEnv))
}
private def initError(msg: String): Throwable = InitialisationError(msg)
case class InitialisationError(msg: String) extends Throwable(msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import smithy4s.kinds._
* An interpreter for unary operations in the AWS_JSON_1.0/AWS_JSON_1.1 protocol
*/
private[aws] class AwsJsonRPCInterpreter[Alg[_[_, _, _, _, _]], Op[_,_,_,_,_], F[_]](
service: smithy4s.Service[Alg, Op],
service: smithy4s.Service.Aux[Alg, Op],
endpointPrefix: String,
awsEnv: AwsEnvironment[F],
contentType: String
Expand Down
13 changes: 7 additions & 6 deletions modules/codegen/src/smithy4s/codegen/Renderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self =>
lines(
line"type ${NameDef(name)}[F[_]] = $FunctorAlgebra_[$nameGen, F]",
block(
line"object ${NameRef(name)} extends $Service_.Provider[$nameGen, ${name}Operation]"
line"object ${NameRef(name)} extends $Service_.Provider[$nameGen]"
)(
line"def apply[F[_]](implicit F: ${NameRef(name)}[F]): F.type = F",
line"def service: $Service_[$nameGen, ${name}Operation] = $nameGen",
line"def service: $Service_[$nameGen] = $nameGen",
line"val id: $ShapeId_ = service.id"
)
)
Expand Down Expand Up @@ -205,7 +205,7 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self =>
newline,
obj(
genNameRef,
ext = line"$Service_[$genNameRef, $opTraitNameRef]"
ext = line"$Service_.Mixin[$genNameRef, $opTraitNameRef]"
)(
newline,
line"def apply[F[_]](implicit F: $FunctorAlgebra_[$genNameRef, F]): F.type = F",
Expand All @@ -214,7 +214,7 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self =>
newline,
renderHintsVal(hints),
newline,
line"val endpoints: $list[$Endpoint_[$opTraitNameRef, _, _, _, _, _]] = $list"
line"val endpoints: $list[$genNameRef.Endpoint[_, _, _, _, _]] = $list"
.args(ops.map(_.name)),
newline,
line"""val version: String = "$version"""",
Expand Down Expand Up @@ -296,6 +296,7 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self =>
val params = if (op.input != Type.unit) {
line"input: ${op.input}"
} else Line.empty
val genServiceName = serviceName + "Gen"
val opName = op.name
val opNameRef = NameRef(opName)
val traitName = NameRef(s"${serviceName}Operation")
Expand Down Expand Up @@ -335,11 +336,11 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self =>

lines(
line"case class ${NameDef(opName)}($params) extends $traitName[${op
.renderAlgParams(serviceName + "Gen")}]",
.renderAlgParams(genServiceName)}]",
obj(
opNameRef,
ext =
line"$Endpoint_[${traitName}, ${op.renderAlgParams(serviceName + "Gen")}]$errorable"
line"$genServiceName.Endpoint[${op.renderAlgParams(genServiceName)}]$errorable"
)(
renderId(op.shapeId),
line"val input: $Schema_[${op.input}] = ${op.input.schemaRef}.addHints(smithy4s.internals.InputOutput.Input.widen)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import smithy.test._
import smithy4s.compliancetests.ComplianceTest.ComplianceResult
import smithy4s.http.CodecAPI
import smithy4s.Document
import smithy4s.Endpoint
import smithy4s.http.PayloadError
import smithy4s.Service
import smithy4s.ShapeTag
Expand All @@ -47,18 +46,18 @@ import org.http4s.Header

abstract class ClientHttpComplianceTestCase[
P,
Alg[_[_, _, _, _, _]],
Op[_, _, _, _, _]
Alg[_[_, _, _, _, _]]
](
protocol: P
protocol: P,
serviceProvider: Service.Provider[Alg]
)(implicit
service: Service[Alg, Op],
ce: CompatEffect,
protocolTag: ShapeTag[P]
) {
import ce._
import org.http4s.implicits._
private val baseUri = uri"http://localhost/"
private[compliancetests] val service = serviceProvider.service

def getClient(app: HttpApp[IO]): Resource[IO, FunctorAlgebra[Alg, IO]]
def codecs: CodecAPI
Expand Down Expand Up @@ -111,7 +110,7 @@ abstract class ClientHttpComplianceTestCase[
}

private[compliancetests] def clientRequestTest[I, E, O, SE, SO](
endpoint: Endpoint[Op, I, E, O, SE, SO],
endpoint: service.Endpoint[I, E, O, SE, SO],
testCase: HttpRequestTestCase
): ComplianceTest[IO] = {
type R[I_, E_, O_, SE_, SO_] = IO[O_]
Expand Down Expand Up @@ -156,7 +155,7 @@ abstract class ClientHttpComplianceTestCase[
}

private[compliancetests] def clientResponseTest[I, E, O, SE, SO](
endpoint: Endpoint[Op, I, E, O, SE, SO],
endpoint: service.Endpoint[I, E, O, SE, SO],
testCase: HttpResponseTestCase,
errorSchema: Option[ErrorResponseTest[_, E]] = None
): ComplianceTest[IO] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import org.http4s._
import org.http4s.headers.`Content-Type`
import smithy.test._
import smithy4s.Document
import smithy4s.Endpoint
import smithy4s.http.CodecAPI
import smithy4s.Service
import smithy4s.ShapeTag
Expand All @@ -38,22 +37,22 @@ import smithy4s.Errorable

abstract class ServerHttpComplianceTestCase[
P,
Alg[_[_, _, _, _, _]],
Op[_, _, _, _, _]
Alg[_[_, _, _, _, _]]
](
protocol: P
protocol: P,
serviceProvider: Service.Provider[Alg]
)(implicit
originalService: Service[Alg, Op],
ce: CompatEffect,
protocolTag: ShapeTag[P]
) {
import ce._
import org.http4s.implicits._
private[compliancetests] val originalService = serviceProvider.service
private val baseUri = uri"http://localhost/"

def getServer[Alg2[_[_, _, _, _, _]], Op2[_, _, _, _, _]](
def getServer[Alg2[_[_, _, _, _, _]]](
impl: FunctorAlgebra[Alg2, IO]
)(implicit s: Service[Alg2, Op2]): Resource[IO, HttpRoutes[IO]]
)(implicit s: Service[Alg2]): Resource[IO, HttpRoutes[IO]]
def codecs: CodecAPI

private def makeRequest(
Expand Down Expand Up @@ -108,21 +107,20 @@ abstract class ServerHttpComplianceTestCase[
}

private[compliancetests] def serverRequestTest[I, E, O, SE, SO](
endpoint: Endpoint[Op, I, E, O, SE, SO],
endpoint: originalService.Endpoint[I, E, O, SE, SO],
testCase: HttpRequestTestCase
): ComplianceTest[IO] = {
type R[I_, E_, O_, SE_, SO_] = IO[O_]

val inputFromDocument = Document.Decoder.fromSchema(endpoint.input)
ComplianceTest[IO](
name = endpoint.id.toString + "(server|request): " + testCase.id,
run = {
deferred[I].flatMap { inputDeferred =>
val fakeImpl: FunctorAlgebra[Alg, IO] =
originalService.fromPolyFunction[R](
new FunctorInterpreter[Op, IO] {
originalService.fromPolyFunction[Kind1[IO]#toKind5](
new originalService.FunctorInterpreter[IO] {
def apply[I_, E_, O_, SE_, SO_](
op: Op[I_, E_, O_, SE_, SO_]
op: originalService.Operation[I_, E_, O_, SE_, SO_]
): IO[O_] = {
val (in, endpointInternal) = originalService.endpoint(op)

Expand Down Expand Up @@ -154,7 +152,7 @@ abstract class ServerHttpComplianceTestCase[
}

private[compliancetests] def serverResponseTest[I, E, O, SE, SO](
endpoint: Endpoint[Op, I, E, O, SE, SO],
endpoint: originalService.Endpoint[I, E, O, SE, SO],
testCase: HttpResponseTestCase,
errorSchema: Option[ErrorResponseTest[_, E]] = None
): ComplianceTest[IO] = {
Expand Down Expand Up @@ -232,11 +230,11 @@ abstract class ServerHttpComplianceTestCase[

private case class NoInputOp[I_, E_, O_, SE_, SO_]()
private def prepareService[I, E, O, SE, SO](
endpoint: Endpoint[Op, I, E, O, SE, SO]
endpoint: originalService.Endpoint[I, E, O, SE, SO]
): (Service.Reflective[NoInputOp], Request[IO]) = {
val amendedEndpoint =
// format: off
new Endpoint[NoInputOp, Unit, E, O, Nothing, Nothing] {
new smithy4s.Endpoint[NoInputOp, Unit, E, O, Nothing, Nothing] {
def hints: smithy4s.Hints = {
val newHttp = smithy.api.Http(
method = smithy.api.NonEmptyString("GET"),
Expand All @@ -263,8 +261,8 @@ abstract class ServerHttpComplianceTestCase[
// format: off
new Service.Reflective[NoInputOp] {
override def id: ShapeId = ShapeId("custom", "service")
override def endpoints: List[Endpoint[NoInputOp, _, _, _, _, _]] = List(amendedEndpoint)
override def endpoint[I_, E_, O_, SI_, SO_](op: NoInputOp[I_, E_, O_, SI_, SO_]): (I_, Endpoint[NoInputOp, I_, E_, O_, SI_, SO_]) = ???
override def endpoints: List[Endpoint[_, _, _, _, _]] = List(amendedEndpoint)
override def endpoint[I_, E_, O_, SI_, SO_](op: NoInputOp[I_, E_, O_, SI_, SO_]): (I_, Endpoint[I_, E_, O_, SI_, SO_]) = ???
override def version: String = originalService.version
override def hints: Hints = originalService.hints
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,9 @@ import weaver._
import smithy4s.Service

object WeaverComplianceTest extends SimpleIOSuite {
val clientTestGenerator = new ClientHttpComplianceTestCase[
alloy.SimpleRestJson,
HelloServiceGen,
HelloServiceOperation
](
alloy.SimpleRestJson()
val clientTestGenerator = new ClientHttpComplianceTestCase(
alloy.SimpleRestJson(),
HelloService
) {
import org.http4s.implicits._
private val baseUri = uri"http://localhost/"
Expand All @@ -44,20 +41,15 @@ object WeaverComplianceTest extends SimpleIOSuite {
def codecs = SimpleRestJsonBuilder.codecs
}

val serverTestGenerator = new ServerHttpComplianceTestCase[
alloy.SimpleRestJson,
HelloServiceGen,
HelloServiceOperation
](
alloy.SimpleRestJson()
) {
def getServer[Alg2[_[_, _, _, _, _]], Op2[_, _, _, _, _]](
impl: smithy4s.kinds.FunctorAlgebra[Alg2, IO]
)(implicit s: Service[Alg2, Op2]): Resource[IO, HttpRoutes[IO]] =
SimpleRestJsonBuilder(s).routes(impl).resource
val serverTestGenerator =
new ServerHttpComplianceTestCase(alloy.SimpleRestJson(), HelloService) {
def getServer[Alg2[_[_, _, _, _, _]]](
impl: smithy4s.kinds.FunctorAlgebra[Alg2, IO]
)(implicit s: Service[Alg2]): Resource[IO, HttpRoutes[IO]] =
SimpleRestJsonBuilder(s).routes(impl).resource

def codecs = SimpleRestJsonBuilder.codecs
}
def codecs = SimpleRestJsonBuilder.codecs
}

val tests: List[ComplianceTest[IO]] =
clientTestGenerator.allClientTests() ++ serverTestGenerator.allServerTests()
Expand Down
6 changes: 3 additions & 3 deletions modules/core/src-2/generated/kinds/functorK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package smithy4s
package kinds

trait FunctorK[Alg[_[_]]]{
trait FunctorK[Alg[_[_]]] {
def mapK[F[_], G[_]](alg: Alg[F], function: PolyFunction[F, G]): Alg[G]
}
object FunctorK {
Expand All @@ -30,7 +30,7 @@ object FunctorK {
}
}

trait FunctorK2[Alg[_[_, _]]]{
trait FunctorK2[Alg[_[_, _]]] {
def mapK2[F[_, _], G[_, _]](alg: Alg[F], function: PolyFunction2[F, G]): Alg[G]
}
object FunctorK2 {
Expand All @@ -41,7 +41,7 @@ object FunctorK2 {
}
}

trait FunctorK5[Alg[_[_, _, _, _, _]]]{
trait FunctorK5[Alg[_[_, _, _, _, _]]] {
def mapK5[F[_, _, _, _, _], G[_, _, _, _, _]](alg: Alg[F], function: PolyFunction5[F, G]): Alg[G]
}
object FunctorK5 {
Expand Down
6 changes: 3 additions & 3 deletions modules/core/src-2/generated/kinds/kinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
package smithy4s
package kinds

object Kind1{
object Kind1 {
type Existential[F[_]] = F[_]
@inline def existential[F[_], A0](fa: F[A0]): F[_] = fa.asInstanceOf[F[_]]
}

object Kind2{
object Kind2 {
type Existential[F[_, _]] = F[_, _]
@inline def existential[F[_, _], A0, A1](fa: F[A0, A1]): F[_, _] = fa.asInstanceOf[F[_, _]]
}

object Kind5{
object Kind5 {
type Existential[F[_, _, _, _, _]] = F[_, _, _, _, _]
@inline def existential[F[_, _, _, _, _], A0, A1, A2, A3, A4](fa: F[A0, A1, A2, A3, A4]): F[_, _, _, _, _] = fa.asInstanceOf[F[_, _, _, _, _]]
}
Loading

0 comments on commit 4006e3d

Please sign in to comment.