-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add hint mask construct #70
Conversation
smithy4s.http.json.codecs( | ||
HintMask() | ||
) // TODO smithy4s.api.SimpleRestJson.hintMask?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great it we could apply the hint mask across the codecs from the SimpleProtocolBuilder
rather than needing to do it everywhere. The issue I had with doing this was that the SimpleProtocolBuilder
does not have direct access to the schematic (it works with the CodecAPI
).
My initial thought here was that we could codegen the hintMask for protocols as part of the rendering. Not sure if there is a better way. The current protocols only have a list of TraitShapeId
like: smithy.api.ProtocolDefinition(Some(List(smithy.api.TraitShapeId("smithy.api#cors"), ...
. I tried looking at the renderer, but couldn't confidently figure out how to begin approaching this 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great it we could apply the hint mask across the codecs from the SimpleProtocolBuilder
We could add a method to the CodecAPI interface tbh.
I tried looking at the renderer, but couldn't confidently figure out how to begin approaching this
that's cool, we'll have a brainstorm next week, but the progress at this point in time is already very satisfying.
@protocolDefinition(traits: [ | ||
"smithy.api#cors", | ||
"smithy.api#endpoint", | ||
"smithy.api#hostLabel", | ||
"smithy.api#http", | ||
"smithy.api#httpError", | ||
"smithy.api#httpHeader", | ||
"smithy.api#httpLabel", | ||
"smithy.api#httpPayload", | ||
"smithy.api#httpPrefixHeaders", | ||
"smithy.api#httpQuery", | ||
"smithy.api#httpQueryParams", | ||
"smithy.api#httpResponseCode", | ||
"smithy.api#jsonName", | ||
"smithy.api#timestampFormat" | ||
]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all just copied from the aws restJson1 protocol. Some of them may not apply here and we have a few others that need to be added (e.g. discriminated)
@@ -113,4 +113,8 @@ package object syntax | |||
OneOf(oneOf.label, oneOf.schema.withHints(hints: _*), oneOf.inject) | |||
} | |||
|
|||
implicit class withMaskSyntax[F[_]](val s: Schematic[F]) extends AnyVal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s should be private, otherwise you can do schematic.s.s.s.s.s I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmm not sure it should leave there tbh, nor that it should be a extension, but 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, I think it has proved less useful than I thought it would initially anyway
@@ -14,7 +14,22 @@ namespace smithy4s.api | |||
@uuidFormat | |||
string UUID | |||
|
|||
@protocolDefinition | |||
@protocolDefinition(traits: [ | |||
"smithy.api#cors", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does @discriminated belong here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also @ error, if it's a thing (can't remember, on phone, just spitballing)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't see the previous comments when I was writing this :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries :) appreciate the comments!
"smithy.api#httpHeader", | ||
"smithy.api#httpLabel", | ||
"smithy.api#httpPayload", | ||
"smithy.api#httpPrefixHeaders", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gotta learn what this is :D
abstract class HintMask { | ||
protected def toSet: Set[Hints.Key[_]] | ||
def ++(other: HintMask): HintMask | ||
def apply(hints: Hints): Hints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice :)
private[this] final class MaskSchematic[F[_]]( | ||
schematic: Schematic[F], | ||
mask: HintMask | ||
) extends PassthroughSchematic[F](schematic) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea !
mask: HintMask | ||
) extends PassthroughSchematic[F](schematic) { | ||
override def withHints[A](fa: F[A], hints: Hints): F[A] = | ||
schematic.withHints(fa, mask(hints)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
class PassthroughSchematic[F[_]](schematic: Schematic[F]) | ||
extends Schematic[F] | ||
with GenericAritySchematic[F] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So unfortunately, this Passthrough
construct should not extend this. We'll have to use the build-time Boilerplate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that because the schematics passed in may not be using the generic arity trait so they would rely on the other functions directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes indeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could just delete the non-generic arity methods in the schematic interface. I think experience shows that we always use the generic one anyway.
We would however keep the arity-based methods in the syntax package, to create schemas. They would just all delegate to the generic-arity one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I am fine with that. I just implemented them all in case we decide to go that route.. I agree though that the generic route seems to be sufficient.
def mask(hintMask: HintMask): Schematic[F] = HintMask.mask(s, hintMask) | ||
} | ||
|
||
implicit def newTypeToHintKey[A](a: Newtype[A]): Hints.Key[_] = a.key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if you return Hints.Key[A]
here ? Does the generated code still compile ? If it does, we should do that, and maybe move this implicit def into the companion object of Hints.Key
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I will give that a try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't compile like that:
type mismatch;
found : smithy4s.Hints.Key[a.Type]
required: smithy4s.Hints.Key[A]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to the companion object though as I think that is better
if ( | ||
hints.contains(Hint.ClientError) || hints.contains(Hint.ServerError) | ||
) { | ||
if (hints.contains(Hint.Error)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -40,7 +40,7 @@ trait CodecAPI { | |||
* @param schema the value's schema | |||
* @return the codec associated to the A value. | |||
*/ | |||
def compileCodec[A](schema: Schema[A]): Codec[A] | |||
def compileCodec[A](schema: Schema[A], hintMask: HintMask): Codec[A] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like this, the application of the hintMask should be an implementation detail of the CodecAPI
instances I think
object SimpleRestJsonBuilder | ||
extends SimpleProtocolBuilder[smithy4s.api.SimpleRestJson]( | ||
smithy4s.http.json.codecs | ||
smithy4s.http.json.codecs( | ||
smithy4s.api.SimpleRestJson.protocol.hintMask ++ HintMask(InputOutput) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick (if-minor): Kind of makes me think the standard hints (smithy.api) should always be forwarded no matter what.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah : imagine you want to have a json RPC API and also serve it over http/restJson. You need a mechanism to ignore the http binding traits when using the RPC protocol (or re-implement a bespoke schematic)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like smithy.api
is too generic a package then 😅
Co-authored-by: Olivier Mélois <[email protected]>
Introduces the concept of
HintMask
that is derived from smithy protocolDefinitions