diff --git a/build.sbt b/build.sbt index 917cd538b..17a82248e 100644 --- a/build.sbt +++ b/build.sbt @@ -567,7 +567,8 @@ lazy val example = projectMatrix "smithy4s.example", "smithy4s.example.import_test", "smithy4s.example.imp", - "smithy4s.example.error" + "smithy4s.example.error", + "smithy4s.example.common" ), smithySpecs := Seq( (ThisBuild / baseDirectory).value / "sampleSpecs" / "example.smithy", @@ -576,7 +577,9 @@ lazy val example = projectMatrix (ThisBuild / baseDirectory).value / "sampleSpecs" / "operation.smithy", (ThisBuild / baseDirectory).value / "sampleSpecs" / "import.smithy", (ThisBuild / baseDirectory).value / "sampleSpecs" / "importerror.smithy", - (ThisBuild / baseDirectory).value / "sampleSpecs" / "adtMember.smithy" + (ThisBuild / baseDirectory).value / "sampleSpecs" / "adtMember.smithy", + (ThisBuild / baseDirectory).value / "sampleSpecs" / "brands.smithy", + (ThisBuild / baseDirectory).value / "sampleSpecs" / "brandscommon.smithy" ), Compile / resourceDirectory := (ThisBuild / baseDirectory).value / "modules" / "example" / "resources", isCE3 := true, diff --git a/modules/codegen/src/smithy4s/codegen/Renderer.scala b/modules/codegen/src/smithy4s/codegen/Renderer.scala index c41c7be69..8a8f2b636 100644 --- a/modules/codegen/src/smithy4s/codegen/Renderer.scala +++ b/modules/codegen/src/smithy4s/codegen/Renderer.scala @@ -631,16 +631,17 @@ private[codegen] class Renderer(compilationUnit: CompilationUnit) { self => } implicit class TypeExt(tpe: Type) { - def schemaRef: String = tpe match { - case Type.PrimitiveType(p) => schemaRefP(p) - case Type.List(member) => s"list(${member.schemaRef})" - case Type.Set(member) => s"set(${member.schemaRef})" - case Type.Map(key, value) => s"map(${key.schemaRef}, ${value.schemaRef})" - case Type.Alias(_, name, Type.PrimitiveType(_)) => - s"$name.schema" - case Type.Alias(_, name, _) => - s"$name.underlyingSchema" - case Type.Ref(_, name) => s"$name.schema" + def schemaRef: Line = tpe match { + case Type.PrimitiveType(p) => Line(schemaRefP(p)) + case Type.List(member) => line"list(${member.schemaRef})" + case Type.Set(member) => line"set(${member.schemaRef})" + case Type.Map(key, value) => + line"map(${key.schemaRef}, ${value.schemaRef})" + case Type.Alias(ns, name, Type.PrimitiveType(_)) => + line"$name.schema".addImport(ns + "." + name) + case Type.Alias(ns, name, _) => + line"$name.underlyingSchema".addImport(ns + "." + name) + case Type.Ref(ns, name) => line"$name.schema".addImport(ns + "." + name) } private def schemaRefP(primitive: Primitive): String = primitive match { diff --git a/modules/codegen/src/smithy4s/codegen/ToLine.scala b/modules/codegen/src/smithy4s/codegen/ToLine.scala index dfc0c1bc3..7a575c26c 100644 --- a/modules/codegen/src/smithy4s/codegen/ToLine.scala +++ b/modules/codegen/src/smithy4s/codegen/ToLine.scala @@ -44,9 +44,8 @@ object ToLine { Line(kimports ++ vimports, s"Map[${k.mkString("")}, ${v.mkString("")}]") case Type.Alias(ns, name, Type.PrimitiveType(_)) => Line(Set(s"$ns.$name"), name) - case Type.Alias(ns, name, aliased) => - val (imports, t) = render(aliased).tupled - Line(imports + s"$ns.$name", t) + case Type.Alias(_, _, aliased) => + render(aliased) case Type.Ref(namespace, name) => val imports = Set(s"$namespace.$name") Line(imports, name) @@ -78,6 +77,7 @@ object ToLine { case class Line(imports: Set[String], line: String) { def tupled = (imports, line) def suffix(suffix: Line) = modify(s => s"$s $suffix") + def addImport(imp: String) = copy(imports = imports + imp) def modify(f: String => String) = Line(imports, f(line)) def nonEmpty = line.nonEmpty def toLines = Lines(imports, List(line)) diff --git a/modules/example/src/smithy4s/example/AddBrandsInput.scala b/modules/example/src/smithy4s/example/AddBrandsInput.scala new file mode 100644 index 000000000..8c62ddc78 --- /dev/null +++ b/modules/example/src/smithy4s/example/AddBrandsInput.scala @@ -0,0 +1,17 @@ +package smithy4s.example + +import smithy4s.example.common.BrandList +import smithy4s.schema.Schema._ + +case class AddBrandsInput(brands: Option[List[String]] = None) +object AddBrandsInput extends smithy4s.ShapeTag.Companion[AddBrandsInput] { + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example", "AddBrandsInput") + + val hints : smithy4s.Hints = smithy4s.Hints.empty + + implicit val schema: smithy4s.Schema[AddBrandsInput] = struct( + BrandList.underlyingSchema.optional[AddBrandsInput]("brands", _.brands), + ){ + AddBrandsInput.apply + }.withId(id).addHints(hints) +} \ No newline at end of file diff --git a/modules/example/src/smithy4s/example/BrandService.scala b/modules/example/src/smithy4s/example/BrandService.scala new file mode 100644 index 000000000..f2064eeaa --- /dev/null +++ b/modules/example/src/smithy4s/example/BrandService.scala @@ -0,0 +1,61 @@ +package smithy4s.example + +import smithy4s.schema.Schema._ + +trait BrandServiceGen[F[_, _, _, _, _]] { + self => + + def addBrands(brands: Option[List[String]] = None) : F[AddBrandsInput, Nothing, Unit, Nothing, Nothing] + + def transform[G[_, _, _, _, _]](transformation : smithy4s.Transformation[F, G]) : BrandServiceGen[G] = new Transformed(transformation) + class Transformed[G[_, _, _, _, _]](transformation : smithy4s.Transformation[F, G]) extends BrandServiceGen[G] { + def addBrands(brands: Option[List[String]] = None) = transformation[AddBrandsInput, Nothing, Unit, Nothing, Nothing](self.addBrands(brands)) + } +} + +object BrandServiceGen extends smithy4s.Service[BrandServiceGen, BrandServiceOperation] { + + def apply[F[_]](implicit F: smithy4s.Monadic[BrandServiceGen, F]): F.type = F + + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example", "BrandService") + + val hints : smithy4s.Hints = smithy4s.Hints.empty + + val endpoints = List( + AddBrands, + ) + + val version: String = "1" + + def endpoint[I, E, O, SI, SO](op : BrandServiceOperation[I, E, O, SI, SO]) = op match { + case AddBrands(input) => (input, AddBrands) + } + + object reified extends BrandServiceGen[BrandServiceOperation] { + def addBrands(brands: Option[List[String]] = None) = AddBrands(AddBrandsInput(brands)) + } + + def transform[P[_, _, _, _, _]](transformation: smithy4s.Transformation[BrandServiceOperation, P]): BrandServiceGen[P] = reified.transform(transformation) + + def transform[P[_, _, _, _, _], P1[_, _, _, _, _]](alg: BrandServiceGen[P], transformation: smithy4s.Transformation[P, P1]): BrandServiceGen[P1] = alg.transform(transformation) + + def asTransformation[P[_, _, _, _, _]](impl : BrandServiceGen[P]): smithy4s.Transformation[BrandServiceOperation, P] = new smithy4s.Transformation[BrandServiceOperation, P] { + def apply[I, E, O, SI, SO](op : BrandServiceOperation[I, E, O, SI, SO]) : P[I, E, O, SI, SO] = op match { + case AddBrands(AddBrandsInput(brands)) => impl.addBrands(brands) + } + } + case class AddBrands(input: AddBrandsInput) extends BrandServiceOperation[AddBrandsInput, Nothing, Unit, Nothing, Nothing] + object AddBrands extends smithy4s.Endpoint[BrandServiceOperation, AddBrandsInput, Nothing, Unit, Nothing, Nothing] { + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example", "AddBrands") + val input: smithy4s.Schema[AddBrandsInput] = AddBrandsInput.schema.addHints(smithy4s.internals.InputOutput.Input.widen) + val output: smithy4s.Schema[Unit] = unit.addHints(smithy4s.internals.InputOutput.Output.widen) + val streamedInput : smithy4s.StreamingSchema[Nothing] = smithy4s.StreamingSchema.nothing + val streamedOutput : smithy4s.StreamingSchema[Nothing] = smithy4s.StreamingSchema.nothing + val hints : smithy4s.Hints = smithy4s.Hints( + smithy.api.Http(smithy.api.NonEmptyString("POST"), smithy.api.NonEmptyString("/brands"), Some(200)), + ) + def wrap(input: AddBrandsInput) = AddBrands(input) + } +} + +sealed trait BrandServiceOperation[Input, Err, Output, StreamedInput, StreamedOutput] diff --git a/modules/example/src/smithy4s/example/common/BrandList.scala b/modules/example/src/smithy4s/example/common/BrandList.scala new file mode 100644 index 000000000..0db8955d9 --- /dev/null +++ b/modules/example/src/smithy4s/example/common/BrandList.scala @@ -0,0 +1,11 @@ +package smithy4s.example.common + +import smithy4s.Newtype +import smithy4s.schema.Schema._ + +object BrandList extends Newtype[List[String]] { + val id: smithy4s.ShapeId = smithy4s.ShapeId("smithy4s.example.common", "BrandList") + val hints : smithy4s.Hints = smithy4s.Hints.empty + val underlyingSchema : smithy4s.Schema[List[String]] = list(string).withId(id).addHints(hints) + implicit val schema : smithy4s.Schema[BrandList] = bijection(underlyingSchema, BrandList(_), (_ : BrandList).value) +} \ No newline at end of file diff --git a/modules/example/src/smithy4s/example/common/package.scala b/modules/example/src/smithy4s/example/common/package.scala new file mode 100644 index 000000000..7db963c51 --- /dev/null +++ b/modules/example/src/smithy4s/example/common/package.scala @@ -0,0 +1,7 @@ +package smithy4s.example + +package object common { + + type BrandList = smithy4s.example.common.BrandList.Type + +} \ No newline at end of file diff --git a/modules/example/src/smithy4s/example/package.scala b/modules/example/src/smithy4s/example/package.scala index 92eab9f7b..5111cb527 100644 --- a/modules/example/src/smithy4s/example/package.scala +++ b/modules/example/src/smithy4s/example/package.scala @@ -13,6 +13,12 @@ package object example { def service : smithy4s.Service[FooServiceGen, FooServiceOperation] = FooServiceGen val id: smithy4s.ShapeId = service.id } + type BrandService[F[_]] = smithy4s.Monadic[BrandServiceGen, F] + object BrandService extends smithy4s.Service.Provider[BrandServiceGen, BrandServiceOperation] { + def apply[F[_]](implicit F: BrandService[F]): F.type = F + def service : smithy4s.Service[BrandServiceGen, BrandServiceOperation] = BrandServiceGen + val id: smithy4s.ShapeId = service.id + } type ObjectService[F[_]] = smithy4s.Monadic[ObjectServiceGen, F] object ObjectService extends smithy4s.Service.Provider[ObjectServiceGen, ObjectServiceOperation] { def apply[F[_]](implicit F: ObjectService[F]): F.type = F diff --git a/sampleSpecs/brands.smithy b/sampleSpecs/brands.smithy new file mode 100644 index 000000000..c785fa8ad --- /dev/null +++ b/sampleSpecs/brands.smithy @@ -0,0 +1,17 @@ +namespace smithy4s.example + +use smithy4s.example.common#BrandList + +service BrandService { + version: "1", + operations: [AddBrands] +} + +@http(method: "POST", uri: "/brands", code: 200) +operation AddBrands { + input: AddBrandsInput +} + +structure AddBrandsInput { + brands: BrandList +} diff --git a/sampleSpecs/brandscommon.smithy b/sampleSpecs/brandscommon.smithy new file mode 100644 index 000000000..1f02b8720 --- /dev/null +++ b/sampleSpecs/brandscommon.smithy @@ -0,0 +1,5 @@ +namespace smithy4s.example.common + +list BrandList { + member: String +}