Skip to content

Commit

Permalink
Conver to Scala CLI project
Browse files Browse the repository at this point in the history
  • Loading branch information
keynmol committed Apr 14, 2024
1 parent 6151da1 commit 569c37c
Show file tree
Hide file tree
Showing 22 changed files with 734 additions and 59 deletions.
11 changes: 11 additions & 0 deletions app/App.scala
@@ -1,3 +1,14 @@
//> using scala 3.3.3
//> using dep com.disneystreaming.smithy4s::smithy4s-aws-http4s::0.18.0-12-da4b23a
//> using dep com.disneystreaming.smithy4s::smithy4s-http4s::0.18.0-12-da4b23a
//> using dep org.http4s::http4s-ember-server::0.23.26
//> using dep org.http4s::http4s-ember-client::0.23.26
//> using dep org.http4s::http4s-scalatags::0.25.2
//> using dep com.outr::scribe-cats::3.13.2
//> using dep com.outr::scribe-json-circe::3.13.2
//> using dep com.outr::scribe-slf4j::3.13.2
//> using dep com.lihaoyi::scalatags::0.12.0

import cats.effect.*
import cats.syntax.all.*
import com.amazonaws.comprehend.*
Expand Down
23 changes: 9 additions & 14 deletions app/Dockerfile
@@ -1,37 +1,32 @@
FROM eclipse-temurin:21 as builder

# Wget is needed to bootstrap SBT
RUN apt update && apt install wget
RUN apt update && apt install -y wget make

WORKDIR /app

# bootstrap SBT
RUN wget https://raw.githubusercontent.com/sbt/sbt/1.10.x/sbt && chmod +x ./sbt
# we only copy the single file that affects which version of SBT gets bootstrapped
# This allows us to cache these steps if you don't change SBT version
COPY project/build.properties project/build.properties
# Start SBT with a dummy command so that it can pre-fetch all the dependencies required
RUN ./sbt --sbt-create version
RUN wget https://raw.githubusercontent.com/VirtusLab/scala-cli/main/scala-cli.sh && mv scala-cli.sh /usr/bin/scala-cli && chmod +x /usr/bin/scala-cli
# Start Scala CLI with a dummy command so that it can pre-fetch all the dependencies required
RUN scala-cli version

# build app
# We copy all the application sources, so the building step will
# run if there are any modifications
COPY build.sbt build.sbt
COPY project/plugins.sbt project/plugins.sbt
COPY App.scala App.scala
COPY smithy smithy
RUN ./sbt stage
COPY aws-generated aws-generated
COPY Makefile Makefile
RUN make assembly

# this is the start of the runtime container - one we will actually ship to AWS
FROM ghcr.io/graalvm/jdk-community:22
RUN mkdir -p /opt
# copy just the built app folder into this container - it doesn't need SBT to run,
# only JVM
COPY --from=builder /app/target/universal/stage /opt/app
COPY --from=builder /app/assembly /opt/app/assembly

ENV SMITHY4S_PORT=80

EXPOSE 80

# run the app
CMD ["/opt/app/bin/app"]
CMD ["/opt/app/assembly"]
7 changes: 7 additions & 0 deletions app/Makefile
@@ -0,0 +1,7 @@
.PHONY: generate assembly

generate:
smithy4s generate --dependencies com.disneystreaming.smithy\:aws-comprehend-spec\:2023.09.22 only.smithy --output aws-generated/

assembly:
scala-cli --power package --assembly App.scala aws-generated -f -o ./assembly
202 changes: 202 additions & 0 deletions app/aws-generated/com/amazonaws/comprehend/Comprehend.scala
@@ -0,0 +1,202 @@
package com.amazonaws.comprehend

import smithy4s.Endpoint
import smithy4s.Hints
import smithy4s.Schema
import smithy4s.Service
import smithy4s.ShapeId
import smithy4s.Transformation
import smithy4s.kinds.PolyFunction5
import smithy4s.kinds.toPolyFunction5.const5
import smithy4s.schema.ErrorSchema
import smithy4s.schema.OperationSchema
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.union

/** <p>Amazon Comprehend is an Amazon Web Services service for gaining insight into the content of documents.
* Use these actions to determine the topics contained in your documents, the topics they
* discuss, the predominant sentiment expressed in them, the predominant language used, and
* more.</p>
*/
trait ComprehendGen[F[_, _, _, _, _]] {
self =>

/** <p>Inspects text and returns an inference of the prevailing sentiment
* (<code>POSITIVE</code>, <code>NEUTRAL</code>, <code>MIXED</code>, or <code>NEGATIVE</code>). </p>
* @param Text
* <p>A UTF-8 text string. The maximum string size is 5 KB.</p>
* @param LanguageCode
* <p>The language of the input documents. You can specify any of the primary languages
* supported by Amazon Comprehend. All documents must be in the same language.</p>
*/
def detectSentiment(text: CustomerInputString, languageCode: LanguageCode): F[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing]

def transform: Transformation.PartiallyApplied[ComprehendGen[F]] = Transformation.of[ComprehendGen[F]](this)
}

object ComprehendGen extends Service.Mixin[ComprehendGen, ComprehendOperation] {

val id: ShapeId = ShapeId("com.amazonaws.comprehend", "Comprehend_20171127")
val version: String = "2017-11-27"

val hints: Hints = Hints(
aws.auth.Sigv4(name = "comprehend"),
smithy.api.Title("Amazon Comprehend"),
aws.protocols.AwsJson1_1(http = None, eventStreamHttp = None),
smithy.api.Documentation("<p>Amazon Comprehend is an Amazon Web Services service for gaining insight into the content of documents.\n Use these actions to determine the topics contained in your documents, the topics they\n discuss, the predominant sentiment expressed in them, the predominant language used, and\n more.</p>"),
aws.api.Service(sdkId = "Comprehend", arnNamespace = Some(aws.api.ArnNamespace("comprehend")), cloudFormationName = Some(aws.api.CloudFormationName("Comprehend")), cloudTrailEventSource = Some("comprehend.amazonaws.com"), endpointPrefix = Some("comprehend")),
).lazily

def apply[F[_]](implicit F: Impl[F]): F.type = F

object ErrorAware {
def apply[F[_, _]](implicit F: ErrorAware[F]): F.type = F
type Default[F[+_, +_]] = Constant[smithy4s.kinds.stubs.Kind2[F]#toKind5]
}

val endpoints: Vector[smithy4s.Endpoint[ComprehendOperation, _, _, _, _, _]] = Vector(
ComprehendOperation.DetectSentiment,
)

def input[I, E, O, SI, SO](op: ComprehendOperation[I, E, O, SI, SO]): I = op.input
def ordinal[I, E, O, SI, SO](op: ComprehendOperation[I, E, O, SI, SO]): Int = op.ordinal
override def endpoint[I, E, O, SI, SO](op: ComprehendOperation[I, E, O, SI, SO]) = op.endpoint
class Constant[P[-_, +_, +_, +_, +_]](value: P[Any, Nothing, Nothing, Nothing, Nothing]) extends ComprehendOperation.Transformed[ComprehendOperation, P](reified, const5(value))
type Default[F[+_]] = Constant[smithy4s.kinds.stubs.Kind1[F]#toKind5]
def reified: ComprehendGen[ComprehendOperation] = ComprehendOperation.reified
def mapK5[P[_, _, _, _, _], P1[_, _, _, _, _]](alg: ComprehendGen[P], f: PolyFunction5[P, P1]): ComprehendGen[P1] = new ComprehendOperation.Transformed(alg, f)
def fromPolyFunction[P[_, _, _, _, _]](f: PolyFunction5[ComprehendOperation, P]): ComprehendGen[P] = new ComprehendOperation.Transformed(reified, f)
def toPolyFunction[P[_, _, _, _, _]](impl: ComprehendGen[P]): PolyFunction5[ComprehendOperation, P] = ComprehendOperation.toPolyFunction(impl)

type DetectSentimentError = ComprehendOperation.DetectSentimentError
val DetectSentimentError = ComprehendOperation.DetectSentimentError
}

sealed trait ComprehendOperation[Input, Err, Output, StreamedInput, StreamedOutput] {
def run[F[_, _, _, _, _]](impl: ComprehendGen[F]): F[Input, Err, Output, StreamedInput, StreamedOutput]
def ordinal: Int
def input: Input
def endpoint: Endpoint[ComprehendOperation, Input, Err, Output, StreamedInput, StreamedOutput]
}

object ComprehendOperation {

object reified extends ComprehendGen[ComprehendOperation] {
def detectSentiment(text: CustomerInputString, languageCode: LanguageCode): DetectSentiment = DetectSentiment(DetectSentimentRequest(text, languageCode))
}
class Transformed[P[_, _, _, _, _], P1[_ ,_ ,_ ,_ ,_]](alg: ComprehendGen[P], f: PolyFunction5[P, P1]) extends ComprehendGen[P1] {
def detectSentiment(text: CustomerInputString, languageCode: LanguageCode): P1[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] = f[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing](alg.detectSentiment(text, languageCode))
}

def toPolyFunction[P[_, _, _, _, _]](impl: ComprehendGen[P]): PolyFunction5[ComprehendOperation, P] = new PolyFunction5[ComprehendOperation, P] {
def apply[I, E, O, SI, SO](op: ComprehendOperation[I, E, O, SI, SO]): P[I, E, O, SI, SO] = op.run(impl)
}
final case class DetectSentiment(input: DetectSentimentRequest) extends ComprehendOperation[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] {
def run[F[_, _, _, _, _]](impl: ComprehendGen[F]): F[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] = impl.detectSentiment(input.text, input.languageCode)
def ordinal: Int = 0
def endpoint: smithy4s.Endpoint[ComprehendOperation,DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] = DetectSentiment
}
object DetectSentiment extends smithy4s.Endpoint[ComprehendOperation,DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] {
val schema: OperationSchema[DetectSentimentRequest, ComprehendOperation.DetectSentimentError, DetectSentimentResponse, Nothing, Nothing] = Schema.operation(ShapeId("com.amazonaws.comprehend", "DetectSentiment"))
.withInput(DetectSentimentRequest.schema)
.withError(DetectSentimentError.errorSchema)
.withOutput(DetectSentimentResponse.schema)
.withHints(smithy.api.Documentation("<p>Inspects text and returns an inference of the prevailing sentiment\n (<code>POSITIVE</code>, <code>NEUTRAL</code>, <code>MIXED</code>, or <code>NEGATIVE</code>). </p>"))
def wrap(input: DetectSentimentRequest): DetectSentiment = DetectSentiment(input)
}
sealed trait DetectSentimentError extends scala.Product with scala.Serializable { self =>
@inline final def widen: DetectSentimentError = this
def $ordinal: Int

object project {
def internalServerException: Option[InternalServerException] = DetectSentimentError.InternalServerExceptionCase.alt.project.lift(self).map(_.internalServerException)
def unsupportedLanguageException: Option[UnsupportedLanguageException] = DetectSentimentError.UnsupportedLanguageExceptionCase.alt.project.lift(self).map(_.unsupportedLanguageException)
def textSizeLimitExceededException: Option[TextSizeLimitExceededException] = DetectSentimentError.TextSizeLimitExceededExceptionCase.alt.project.lift(self).map(_.textSizeLimitExceededException)
def invalidRequestException: Option[InvalidRequestException] = DetectSentimentError.InvalidRequestExceptionCase.alt.project.lift(self).map(_.invalidRequestException)
}

def accept[A](visitor: DetectSentimentError.Visitor[A]): A = this match {
case value: DetectSentimentError.InternalServerExceptionCase => visitor.internalServerException(value.internalServerException)
case value: DetectSentimentError.UnsupportedLanguageExceptionCase => visitor.unsupportedLanguageException(value.unsupportedLanguageException)
case value: DetectSentimentError.TextSizeLimitExceededExceptionCase => visitor.textSizeLimitExceededException(value.textSizeLimitExceededException)
case value: DetectSentimentError.InvalidRequestExceptionCase => visitor.invalidRequestException(value.invalidRequestException)
}
}
object DetectSentimentError extends ErrorSchema.Companion[DetectSentimentError] {

def internalServerException(internalServerException: InternalServerException): DetectSentimentError = InternalServerExceptionCase(internalServerException)
def unsupportedLanguageException(unsupportedLanguageException: UnsupportedLanguageException): DetectSentimentError = UnsupportedLanguageExceptionCase(unsupportedLanguageException)
def textSizeLimitExceededException(textSizeLimitExceededException: TextSizeLimitExceededException): DetectSentimentError = TextSizeLimitExceededExceptionCase(textSizeLimitExceededException)
def invalidRequestException(invalidRequestException: InvalidRequestException): DetectSentimentError = InvalidRequestExceptionCase(invalidRequestException)

val id: ShapeId = ShapeId("com.amazonaws.comprehend", "DetectSentimentError")

val hints: Hints = Hints.empty

final case class InternalServerExceptionCase(internalServerException: InternalServerException) extends DetectSentimentError { final def $ordinal: Int = 0 }
final case class UnsupportedLanguageExceptionCase(unsupportedLanguageException: UnsupportedLanguageException) extends DetectSentimentError { final def $ordinal: Int = 1 }
final case class TextSizeLimitExceededExceptionCase(textSizeLimitExceededException: TextSizeLimitExceededException) extends DetectSentimentError { final def $ordinal: Int = 2 }
final case class InvalidRequestExceptionCase(invalidRequestException: InvalidRequestException) extends DetectSentimentError { final def $ordinal: Int = 3 }

object InternalServerExceptionCase {
val hints: Hints = Hints.empty
val schema: Schema[DetectSentimentError.InternalServerExceptionCase] = bijection(InternalServerException.schema.addHints(hints), DetectSentimentError.InternalServerExceptionCase(_), _.internalServerException)
val alt = schema.oneOf[DetectSentimentError]("InternalServerException")
}
object UnsupportedLanguageExceptionCase {
val hints: Hints = Hints.empty
val schema: Schema[DetectSentimentError.UnsupportedLanguageExceptionCase] = bijection(UnsupportedLanguageException.schema.addHints(hints), DetectSentimentError.UnsupportedLanguageExceptionCase(_), _.unsupportedLanguageException)
val alt = schema.oneOf[DetectSentimentError]("UnsupportedLanguageException")
}
object TextSizeLimitExceededExceptionCase {
val hints: Hints = Hints.empty
val schema: Schema[DetectSentimentError.TextSizeLimitExceededExceptionCase] = bijection(TextSizeLimitExceededException.schema.addHints(hints), DetectSentimentError.TextSizeLimitExceededExceptionCase(_), _.textSizeLimitExceededException)
val alt = schema.oneOf[DetectSentimentError]("TextSizeLimitExceededException")
}
object InvalidRequestExceptionCase {
val hints: Hints = Hints.empty
val schema: Schema[DetectSentimentError.InvalidRequestExceptionCase] = bijection(InvalidRequestException.schema.addHints(hints), DetectSentimentError.InvalidRequestExceptionCase(_), _.invalidRequestException)
val alt = schema.oneOf[DetectSentimentError]("InvalidRequestException")
}

trait Visitor[A] {
def internalServerException(value: InternalServerException): A
def unsupportedLanguageException(value: UnsupportedLanguageException): A
def textSizeLimitExceededException(value: TextSizeLimitExceededException): A
def invalidRequestException(value: InvalidRequestException): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def internalServerException(value: InternalServerException): A = default
def unsupportedLanguageException(value: UnsupportedLanguageException): A = default
def textSizeLimitExceededException(value: TextSizeLimitExceededException): A = default
def invalidRequestException(value: InvalidRequestException): A = default
}
}

implicit val schema: Schema[DetectSentimentError] = union(
DetectSentimentError.InternalServerExceptionCase.alt,
DetectSentimentError.UnsupportedLanguageExceptionCase.alt,
DetectSentimentError.TextSizeLimitExceededExceptionCase.alt,
DetectSentimentError.InvalidRequestExceptionCase.alt,
){
_.$ordinal
}
def liftError(throwable: Throwable): Option[DetectSentimentError] = throwable match {
case e: InternalServerException => Some(DetectSentimentError.InternalServerExceptionCase(e))
case e: UnsupportedLanguageException => Some(DetectSentimentError.UnsupportedLanguageExceptionCase(e))
case e: TextSizeLimitExceededException => Some(DetectSentimentError.TextSizeLimitExceededExceptionCase(e))
case e: InvalidRequestException => Some(DetectSentimentError.InvalidRequestExceptionCase(e))
case _ => None
}
def unliftError(e: DetectSentimentError): Throwable = e match {
case DetectSentimentError.InternalServerExceptionCase(e) => e
case DetectSentimentError.UnsupportedLanguageExceptionCase(e) => e
case DetectSentimentError.TextSizeLimitExceededExceptionCase(e) => e
case DetectSentimentError.InvalidRequestExceptionCase(e) => e
}
}
}

@@ -0,0 +1,17 @@
package com.amazonaws.comprehend

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object CustomerInputString extends Newtype[String] {
val id: ShapeId = ShapeId("com.amazonaws.comprehend", "CustomerInputString")
val hints: Hints = Hints(
smithy.api.Sensitive(),
).lazily
val underlyingSchema: Schema[String] = string.withId(id).addHints(hints).validated(smithy.api.Length(min = Some(1L), max = None))
implicit val schema: Schema[CustomerInputString] = bijection(underlyingSchema, asBijection)
}
@@ -0,0 +1,31 @@
package com.amazonaws.comprehend

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.struct

/** @param Text
* <p>A UTF-8 text string. The maximum string size is 5 KB.</p>
* @param LanguageCode
* <p>The language of the input documents. You can specify any of the primary languages
* supported by Amazon Comprehend. All documents must be in the same language.</p>
*/
final case class DetectSentimentRequest(text: CustomerInputString, languageCode: LanguageCode)

object DetectSentimentRequest extends ShapeTag.Companion[DetectSentimentRequest] {
val id: ShapeId = ShapeId("com.amazonaws.comprehend", "DetectSentimentRequest")

val hints: Hints = Hints(
smithy.api.Input(),
).lazily

// constructor using the original order from the spec
private def make(text: CustomerInputString, languageCode: LanguageCode): DetectSentimentRequest = DetectSentimentRequest(text, languageCode)

implicit val schema: Schema[DetectSentimentRequest] = struct(
CustomerInputString.schema.required[DetectSentimentRequest]("Text", _.text).addHints(smithy.api.Documentation("<p>A UTF-8 text string. The maximum string size is 5 KB.</p>")),
LanguageCode.schema.required[DetectSentimentRequest]("LanguageCode", _.languageCode).addHints(smithy.api.Documentation("<p>The language of the input documents. You can specify any of the primary languages\n supported by Amazon Comprehend. All documents must be in the same language.</p>")),
)(make).withId(id).addHints(hints)
}

0 comments on commit 569c37c

Please sign in to comment.