Skip to content
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

Retain original field ordering in schemas #1427

Merged
merged 7 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
# 0.18.11

* smithy4s Structure schemas are now retaining the original order of fields, as per the specification.

# 0.18.10

* Bumps alloy to 0.3.1. This is required as otherwise the `alloy#nullable` hints get filtered out when using SimpleRestJsonBuilder.
Expand Down
Expand Up @@ -13,5 +13,6 @@ object DescribeEndpointsRequest extends ShapeTag.Companion[DescribeEndpointsRequ

val hints: Hints = Hints.empty


implicit val schema: Schema[DescribeEndpointsRequest] = constant(DescribeEndpointsRequest()).withId(id).addHints(hints)
}
Expand Up @@ -16,9 +16,12 @@ object DescribeEndpointsResponse extends ShapeTag.Companion[DescribeEndpointsRes

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(endpoints: List[Endpoint]): DescribeEndpointsResponse = DescribeEndpointsResponse(endpoints)

implicit val schema: Schema[DescribeEndpointsResponse] = struct(
Endpoints.underlyingSchema.required[DescribeEndpointsResponse]("Endpoints", _.endpoints).addHints(smithy.api.Documentation("<p>List of endpoints.</p>")),
){
DescribeEndpointsResponse.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -23,10 +23,13 @@ object Endpoint extends ShapeTag.Companion[Endpoint] {
smithy.api.Documentation("<p>An endpoint information details.</p>"),
).lazily

// constructor using the original order from the spec
private def make(address: String, cachePeriodInMinutes: Long): Endpoint = Endpoint(address, cachePeriodInMinutes)

implicit val schema: Schema[Endpoint] = struct(
string.required[Endpoint]("Address", _.address).addHints(smithy.api.Documentation("<p>IP address of the endpoint.</p>")),
long.required[Endpoint]("CachePeriodInMinutes", _.cachePeriodInMinutes).addHints(smithy.api.Default(smithy4s.Document.fromDouble(0.0d)), smithy.api.Documentation("<p>Endpoint cache time to live (TTL) value.</p>")),
){
Endpoint.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -23,9 +23,12 @@ object InternalServerError extends ShapeTag.Companion[InternalServerError] {
smithy.api.Error.SERVER.widen,
).lazily

// constructor using the original order from the spec
private def make(message: Option[ErrorMessage]): InternalServerError = InternalServerError(message)

implicit val schema: Schema[InternalServerError] = struct(
ErrorMessage.schema.optional[InternalServerError]("message", _.message).addHints(smithy.api.Documentation("<p>The server encountered an internal error trying to fulfill the request.</p>")),
){
InternalServerError.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -20,9 +20,12 @@ object InvalidEndpointException extends ShapeTag.Companion[InvalidEndpointExcept
smithy.api.HttpError(421),
).lazily

// constructor using the original order from the spec
private def make(message: Option[String]): InvalidEndpointException = InvalidEndpointException(message)

implicit val schema: Schema[InvalidEndpointException] = struct(
string.optional[InvalidEndpointException]("Message", _.message),
){
InvalidEndpointException.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -23,10 +23,13 @@ object ListTablesInput extends ShapeTag.Companion[ListTablesInput] {
smithy.api.Documentation("<p>Represents the input of a <code>ListTables</code> operation.</p>"),
).lazily

// constructor using the original order from the spec
private def make(exclusiveStartTableName: Option[TableName], limit: Option[ListTablesInputLimit]): ListTablesInput = ListTablesInput(exclusiveStartTableName, limit)

implicit val schema: Schema[ListTablesInput] = struct(
TableName.schema.optional[ListTablesInput]("ExclusiveStartTableName", _.exclusiveStartTableName).addHints(smithy.api.Documentation("<p>The first table name that this operation will evaluate. Use the value that was returned for\n <code>LastEvaluatedTableName</code> in a previous operation, so that you can obtain the next page\n of results.</p>")),
ListTablesInputLimit.schema.optional[ListTablesInput]("Limit", _.limit).addHints(smithy.api.Documentation("<p>A maximum number of table names to return. If this parameter is not specified, the limit is 100.</p>")),
){
ListTablesInput.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -28,10 +28,13 @@ object ListTablesOutput extends ShapeTag.Companion[ListTablesOutput] {
smithy.api.Documentation("<p>Represents the output of a <code>ListTables</code> operation.</p>"),
).lazily

// constructor using the original order from the spec
private def make(tableNames: Option[List[TableName]], lastEvaluatedTableName: Option[TableName]): ListTablesOutput = ListTablesOutput(tableNames, lastEvaluatedTableName)

implicit val schema: Schema[ListTablesOutput] = struct(
TableNameList.underlyingSchema.optional[ListTablesOutput]("TableNames", _.tableNames).addHints(smithy.api.Documentation("<p>The names of the tables associated with the current account at the current endpoint. The maximum size of this array is 100.</p>\n <p>If <code>LastEvaluatedTableName</code> also appears in the output, you can use this value as the\n <code>ExclusiveStartTableName</code> parameter in a subsequent <code>ListTables</code> request and\n obtain the next page of results.</p>")),
TableName.schema.optional[ListTablesOutput]("LastEvaluatedTableName", _.lastEvaluatedTableName).addHints(smithy.api.Documentation("<p>The name of the last table in the current page of results. Use this value as the\n <code>ExclusiveStartTableName</code> in a new request to obtain the next page of results, until\n all the table names are returned.</p>\n <p>If you do not receive a <code>LastEvaluatedTableName</code> value in the response, this means that\n there are no more table names to be retrieved.</p>")),
){
ListTablesOutput.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -18,6 +18,9 @@ object Attributes extends ShapeTag.Companion[Attributes] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(user: String, public: Boolean, size: Long, creationDate: Timestamp, region: String, queryable: Option[Boolean], queryableLastChange: Option[Timestamp], blockPublicAccess: Option[Boolean], permissions: Option[List[Permission]], tags: Option[List[String]], backedUp: Option[Boolean], metadata: Option[List[Metadata]], encryption: Option[Encryption]): Attributes = Attributes(user, public, size, creationDate, region, queryable, queryableLastChange, blockPublicAccess, permissions, tags, backedUp, metadata, encryption)

implicit val schema: Schema[Attributes] = struct(
string.required[Attributes]("user", _.user),
boolean.required[Attributes]("public", _.public),
Expand All @@ -33,6 +36,6 @@ object Attributes extends ShapeTag.Companion[Attributes] {
ListMetadata.underlyingSchema.optional[Attributes]("metadata", _.metadata),
Encryption.schema.optional[Attributes]("encryption", _.encryption),
){
Attributes.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,11 +14,14 @@ object CreateObjectInput extends ShapeTag.Companion[CreateObjectInput] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(key: String, bucketName: String, payload: S3Object): CreateObjectInput = CreateObjectInput(key, bucketName, payload)

implicit val schema: Schema[CreateObjectInput] = struct(
string.required[CreateObjectInput]("key", _.key).addHints(smithy.api.HttpLabel()),
string.required[CreateObjectInput]("bucketName", _.bucketName).addHints(smithy.api.HttpLabel()),
S3Object.schema.required[CreateObjectInput]("payload", _.payload).addHints(smithy.api.HttpPayload()),
){
CreateObjectInput.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,10 +14,13 @@ object Creds extends ShapeTag.Companion[Creds] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(user: Option[String], key: Option[String]): Creds = Creds(user, key)

implicit val schema: Schema[Creds] = struct(
string.optional[Creds]("user", _.user),
string.optional[Creds]("key", _.key),
){
Creds.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -16,11 +16,14 @@ object Encryption extends ShapeTag.Companion[Encryption] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(user: Option[String], date: Option[Timestamp], metadata: Option[EncryptionMetadata]): Encryption = Encryption(user, date, metadata)

implicit val schema: Schema[Encryption] = struct(
string.optional[Encryption]("user", _.user),
timestamp.optional[Encryption]("date", _.date).addHints(smithy.api.TimestampFormat.EPOCH_SECONDS.widen),
EncryptionMetadata.schema.optional[Encryption]("metadata", _.metadata),
){
Encryption.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -15,11 +15,14 @@ object EncryptionMetadata extends ShapeTag.Companion[EncryptionMetadata] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(system: Option[String], credentials: Option[Creds], partial: Option[Boolean]): EncryptionMetadata = EncryptionMetadata(system, credentials, partial)

implicit val schema: Schema[EncryptionMetadata] = struct(
string.optional[EncryptionMetadata]("system", _.system),
Creds.schema.optional[EncryptionMetadata]("credentials", _.credentials),
boolean.optional[EncryptionMetadata]("partial", _.partial),
){
EncryptionMetadata.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -17,13 +17,16 @@ object Metadata extends ShapeTag.Companion[Metadata] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(contentType: Option[String], lastModified: Option[Timestamp], checkSum: Option[String], pendingDeletion: Option[Boolean], etag: Option[String]): Metadata = Metadata(contentType, lastModified, checkSum, pendingDeletion, etag)

implicit val schema: Schema[Metadata] = struct(
string.optional[Metadata]("contentType", _.contentType),
timestamp.optional[Metadata]("lastModified", _.lastModified).addHints(smithy.api.TimestampFormat.EPOCH_SECONDS.widen),
string.optional[Metadata]("checkSum", _.checkSum),
boolean.optional[Metadata]("pendingDeletion", _.pendingDeletion),
string.optional[Metadata]("etag", _.etag),
){
Metadata.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,11 +14,14 @@ object Permission extends ShapeTag.Companion[Permission] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(read: Option[Boolean], write: Option[Boolean], directory: Option[Boolean]): Permission = Permission(read, write, directory)

implicit val schema: Schema[Permission] = struct(
boolean.optional[Permission]("read", _.read),
boolean.optional[Permission]("write", _.write),
boolean.optional[Permission]("directory", _.directory),
){
Permission.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -16,12 +16,15 @@ object S3Object extends ShapeTag.Companion[S3Object] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(id: String, owner: String, attributes: Attributes, data: Blob): S3Object = S3Object(id, owner, attributes, data)

implicit val schema: Schema[S3Object] = struct(
string.required[S3Object]("id", _.id),
string.required[S3Object]("owner", _.owner),
Attributes.schema.required[S3Object]("attributes", _.attributes),
bytes.required[S3Object]("data", _.data),
){
S3Object.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,11 +14,14 @@ object SendStringInput extends ShapeTag.Companion[SendStringInput] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(key: String, bucketName: String, body: String): SendStringInput = SendStringInput(key, bucketName, body)

implicit val schema: Schema[SendStringInput] = struct(
string.required[SendStringInput]("key", _.key).addHints(smithy.api.HttpLabel()),
string.required[SendStringInput]("bucketName", _.bucketName).addHints(smithy.api.HttpLabel()),
string.required[SendStringInput]("body", _.body).addHints(smithy.api.HttpPayload()),
){
SendStringInput.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -16,9 +16,12 @@ object AStructure extends ShapeTag.Companion[AStructure] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(astring: AString): AStructure = AStructure(astring)

implicit val schema: Schema[AStructure] = struct(
AString.schema.field[AStructure]("astring", _.astring).addHints(smithy.api.Default(smithy4s.Document.fromString("\"Hello World\" with \"quotes\""))),
){
AStructure.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,9 +14,12 @@ object AddBrandsInput extends ShapeTag.Companion[AddBrandsInput] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(brands: Option[List[String]]): AddBrandsInput = AddBrandsInput(brands)

implicit val schema: Schema[AddBrandsInput] = struct(
BrandList.underlyingSchema.optional[AddBrandsInput]("brands", _.brands),
){
AddBrandsInput.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,10 +14,13 @@ object AddMenuItemRequest extends ShapeTag.Companion[AddMenuItemRequest] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(restaurant: String, menuItem: MenuItem): AddMenuItemRequest = AddMenuItemRequest(restaurant, menuItem)

implicit val schema: Schema[AddMenuItemRequest] = struct(
string.required[AddMenuItemRequest]("restaurant", _.restaurant).addHints(smithy.api.HttpLabel()),
MenuItem.schema.required[AddMenuItemRequest]("menuItem", _.menuItem).addHints(smithy.api.HttpPayload()),
){
AddMenuItemRequest.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -16,10 +16,13 @@ object AddMenuItemResult extends ShapeTag.Companion[AddMenuItemResult] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(itemId: String, added: Timestamp): AddMenuItemResult = AddMenuItemResult(itemId, added)

implicit val schema: Schema[AddMenuItemResult] = struct(
string.required[AddMenuItemResult]("itemId", _.itemId).addHints(smithy.api.HttpPayload()),
timestamp.required[AddMenuItemResult]("added", _.added).addHints(smithy.api.TimestampFormat.EPOCH_SECONDS.widen, smithy.api.HttpHeader("X-ADDED-AT")),
){
AddMenuItemResult.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -15,5 +15,6 @@ object AgeFormat extends ShapeTag.Companion[AgeFormat] {
smithy.api.Trait(selector = Some(":test(integer, member > integer)"), structurallyExclusive = None, conflicts = None, breakingChanges = None),
).lazily


implicit val schema: Schema[AgeFormat] = constant(AgeFormat()).withId(id).addHints(hints)
}
Expand Up @@ -15,5 +15,6 @@ object ArbitraryDataTest extends ShapeTag.Companion[ArbitraryDataTest] {
smithy4s.example.ArbitraryData(smithy4s.Document.obj("str" -> smithy4s.Document.fromString("hello"), "int" -> smithy4s.Document.fromDouble(1.0d), "bool" -> smithy4s.Document.fromBoolean(true), "arr" -> smithy4s.Document.array(smithy4s.Document.fromString("one"), smithy4s.Document.fromString("two"), smithy4s.Document.fromString("three")), "obj" -> smithy4s.Document.obj("str" -> smithy4s.Document.fromString("s"), "i" -> smithy4s.Document.fromDouble(1.0d)))),
).lazily


implicit val schema: Schema[ArbitraryDataTest] = constant(ArbitraryDataTest()).withId(id).addHints(hints)
}
Expand Up @@ -14,6 +14,9 @@ object BigStruct extends ShapeTag.Companion[BigStruct] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int): BigStruct = BigStruct(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23)

implicit val schema: Schema[BigStruct] = struct.genericArity(
int.required[BigStruct]("a1", _.a1),
int.required[BigStruct]("a2", _.a2),
Expand All @@ -39,7 +42,7 @@ object BigStruct extends ShapeTag.Companion[BigStruct] {
int.required[BigStruct]("a22", _.a22),
int.required[BigStruct]("a23", _.a23),
){
arr => new BigStruct(
arr => make(
arr(0).asInstanceOf[Int],
arr(1).asInstanceOf[Int],
arr(2).asInstanceOf[Int],
Expand Down
Expand Up @@ -14,9 +14,12 @@ object Candy extends ShapeTag.Companion[Candy] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(name: Option[String]): Candy = Candy(name)

implicit val schema: Schema[Candy] = struct(
string.optional[Candy]("name", _.name),
){
Candy.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -14,10 +14,13 @@ object CityCoordinates extends ShapeTag.Companion[CityCoordinates] {

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(latitude: Float, longitude: Float): CityCoordinates = CityCoordinates(latitude, longitude)

implicit val schema: Schema[CityCoordinates] = struct(
float.required[CityCoordinates]("latitude", _.latitude),
float.required[CityCoordinates]("longitude", _.longitude),
){
CityCoordinates.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -16,10 +16,13 @@ object CitySummary extends ShapeTag.Companion[CitySummary] {
smithy.api.References(List(smithy.api.Reference(resource = smithy.api.NonEmptyString("smithy4s.example#City"), ids = None, service = None, rel = None))),
).lazily

// constructor using the original order from the spec
private def make(cityId: CityId, name: String): CitySummary = CitySummary(cityId, name)

implicit val schema: Schema[CitySummary] = struct(
CityId.schema.required[CitySummary]("cityId", _.cityId),
string.required[CitySummary]("name", _.name),
){
CitySummary.apply
make
}.withId(id).addHints(hints)
}
Expand Up @@ -19,10 +19,13 @@ object ClientError extends ShapeTag.Companion[ClientError] {
smithy.api.Error.CLIENT.widen,
).lazily

// constructor using the original order from the spec
private def make(code: Int, details: String): ClientError = ClientError(code, details)

implicit val schema: Schema[ClientError] = struct(
int.required[ClientError]("code", _.code),
string.required[ClientError]("details", _.details),
){
ClientError.apply
make
}.withId(id).addHints(hints)
}