softwaremill / sttp-apispec

OpenAPI, AsyncAPI and JSON Schema Scala models.
Apache License 2.0
24 stars 11 forks source link

Added defaults to reduce boilerplate of creating asyncapi #94

Closed soujiro32167 closed 1 year ago

soujiro32167 commented 1 year ago

Use case: I have a bunch of avro codecs, and I want to generate docs for Backstage


import org.apache.avro.Schema
import sttp.apispec.ReferenceOr
import sttp.apispec.asyncapi.*

import scala.collection.immutable.ListMap
import scala.jdk.CollectionConverters.*

case class EventDescription(schema: Schema, topic: String, pubSub: PubSub)

sealed trait PubSub

object PubSub {
  case object Subscribe extends PubSub

  case object Publish extends PubSub
}

def schemaToMessage(schema: Schema): Message =
  if (schema.isUnion)
    OneOfMessage(schema.getTypes.asScala.map(s => Message.singleInline(s.toString, Some("application/vnd.apache.avro+yaml;version=1.9.0"))).toList)
  else
    Message.singleInline(schema.toString, Some("application/vnd.apache.avro+yaml;version=1.9.0"))

def avroChannelMessage(schema: Schema, pubSub: PubSub): ChannelItem =
  pubSub match {
    case PubSub.Publish =>
      ChannelItem.publish(Operation.inlineMessage(schemaToMessage(schema)))
    case PubSub.Subscribe =>
      ChannelItem.subscribe(Operation.inlineMessage(schemaToMessage(schema)))
  }

def mkChannels(events: List[EventDescription]): ListMap[String, ReferenceOr[ChannelItem]] =
  ListMap.from(
    events.map(e => e.topic -> Right(avroChannelMessage(e.schema, e.pubSub)))
  )

def makeAsyncApi(title: String, version: String, events: List[EventDescription]): AsyncAPI = {

  AsyncAPI(
    info = Info(
      title = title,
      version = version
    ),
    channels = mkChannels(events)
  )
}
adamw commented 1 year ago

Thanks!