zio-http icon indicating copy to clipboard operation
zio-http copied to clipboard

OpenAPI extension

Open guersam opened this issue 1 year ago • 7 comments

I'd like to add OpenAPI extensions to endpoints, especially for GPTs Actions.

Example

/api/some/resource:
  get:
    operationId: blah
    x-openai-isConsequential: false
  post:
    operationId: blah2
    x-openai-isConsequential: true

guersam avatar Dec 28 '23 08:12 guersam

I want to discuss:

1. The encoding of extension values

The spec says:

The extension value can be a primitive, an array, an object or null.

Possible types are:

  1. zio.schema.DynamicValue
  2. zio.json.ast.Json
  3. Dedicated AST

Personally I'd prefer Json AST, because it is:

  1. Isomorphic to the spec
  2. Easy for users to build
  3. Already has its own schema

2. Schema derivation

As the extensions should be serialized at the same level as the predefined fields, automatic schema derivation won't work out-of-box.

A solution I thought is to add a transient field and wrap the derived schema with DynamicValue.

case class Foo(
  a: Int,
  b: String,
  @transientField
  extensions: ListMap[String, Json] = ListMap.empty
) {
  def withExtensions(newExtensions: ListMap[String, Json]): Foo = copy(extensions = newExtensions)
}

object Foo {
  private val baseSchema = DeriveSchema.gen[Foo]
  given Schema[Foo] =
    Schema.dynamicValue.transformOrFail( dv =>
      baseSchema.gen[Foo].fromDynamic(dv).map { foo =>
        val ex = ??? // fields with "x-" keys from the DynamicValue
        foo.withExtensions(ex)
      },
      foo => baseSchema.toDynamic(foo) // and then merge extensions
    )
}

What do you think?

guersam avatar Dec 29 '23 02:12 guersam

@987Nabil What do you think?

jdegoes avatar Jan 06 '24 20:01 jdegoes

https://scastie.scala-lang.org/guersam/h1kyN8o8TNiZ9kpXVByPRg/54

Did a quick sketch. Although it worked with the most basic example, it failed with Enumeration, Dictionary and Tuple fields because JsonCodec[DynamicValue] doesn't support them in direct mapping mode.

For this approach, a tolerant mode for Schema[DynamicValue] might be needed but I'm not sure if it's possible.

guersam avatar Jan 08 '24 13:01 guersam

I'll take a look at this. But I have some other priorities. So it might take a week or two. I can't say how to solve this without some research.

987Nabil avatar Jan 09 '24 08:01 987Nabil

@987Nabil Thanks. Now I have more urgent issues to adopt endpoint DSL. I'll report them soon.

guersam avatar Jan 09 '24 08:01 guersam