Skip to content

Commit 2efa5e8

Browse files
authored
add support for Durations and CompactLocalTime (#271)
* add support for Duration and CompactLocalTime * add support for Duration when translating from openAPI and json schema * default to PROTOBUF format for protobuf OffsetDateTime
1 parent 3e8c343 commit 2efa5e8

File tree

19 files changed

+194
-61
lines changed

19 files changed

+194
-61
lines changed

buildDeps.sc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import mill.define._
33
import mill.scalalib._
44

55
object alloy {
6-
val alloyVersion = "0.3.28"
6+
val alloyVersion = "0.3.31"
77
val org = "com.disneystreaming.alloy"
88
val core = ivy"$org:alloy-core:$alloyVersion"
99
val protobuf = ivy"$org:alloy-protobuf:$alloyVersion"

modules/compiler-core/src/internals/IModelToSmithy.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ private[compiler] final class IModelToSmithy(useEnumTraitSyntax: Boolean)
434434
case Year => List(new alloy.YearFormatTrait())
435435
case YearMonth => List(new alloy.YearMonthFormatTrait())
436436
case MonthDay => List(new alloy.MonthDayFormatTrait())
437+
case Duration => List(new alloy.DurationSecondsFormatTrait())
437438
}
438439
case Hint.Tags(values) =>
439440
List(TagsTrait.builder.values(values.asJava).build())

modules/compiler-core/src/internals/PatternFolder.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ private[compiler] final class PatternFolder[F[
108108
case PYear => std("Integer", Hint.Timestamp(TimestampFormat.Year))
109109
case PYearMonth => std("String", Hint.Timestamp(TimestampFormat.YearMonth))
110110
case PMonthDay => std("String", Hint.Timestamp(TimestampFormat.MonthDay))
111+
case PDuration => std("BigDecimal", Hint.Timestamp(TimestampFormat.Duration))
111112
}
112113

113114
def nestedIdFromPrimitive(primitive: Primitive): (DefId, List[Hint]) =
@@ -123,6 +124,7 @@ private[compiler] final class PatternFolder[F[
123124
case PYear => alloy("Year")
124125
case PYearMonth => alloy("YearMonth")
125126
case PMonthDay => alloy("MonthDay")
127+
case PDuration => alloy("Duration")
126128
case _ => topLevelIdFromPrimitive(primitive)
127129
}
128130
// format: on

modules/compiler-core/src/internals/Primitive.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
package smithytranslate.compiler.internals
1717

1818
import java.util.Date
19-
import java.time._
19+
import java.time.{Duration => _, _}
2020
import java.util.UUID
21+
import scala.concurrent.duration.Duration
2122

2223
private[compiler] sealed trait Primitive {
2324
type T
@@ -50,6 +51,7 @@ private[compiler] object Primitive {
5051
case object PYear extends Primitive { type T = Year }
5152
case object PYearMonth extends Primitive { type T = YearMonth }
5253
case object PMonthDay extends Primitive { type T = MonthDay }
54+
case object PDuration extends Primitive { type T = Duration }
5355
case object PBytes extends Primitive { type T = Array[Byte] }
5456
case object PFreeForm extends Primitive { type T = Any }
5557
}

modules/compiler-core/src/internals/TimestampFormat.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ private[compiler] object TimestampFormat {
3333
case object Year extends TimestampFormat
3434
case object YearMonth extends TimestampFormat
3535
case object MonthDay extends TimestampFormat
36+
case object Duration extends TimestampFormat
3637
}

modules/compiler-core/src/internals/postprocess/DropAlloyTimeExtensionsTransformer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ private[compiler] object DropAlloyTimeExtensionsTransformer
3636
"zoned-date-time",
3737
"year",
3838
"year-month",
39-
"month-day"
39+
"month-day",
40+
"duration"
4041
)
4142

4243
private def process(d: Definition) = {

modules/docs/openapi.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Smithy.
6969
| string | binary | Blob | |
7070
| string | byte | Blob | |
7171
| string | password | String | @sensitive |
72+
| number | duration | Duration | alloy#durationSecondsFormat |
7273
| number | float | Float | |
7374
| number | double | Double | |
7475
| number | double | Double | |
@@ -132,6 +133,9 @@ components:
132133
MyMonthDay:
133134
type: string
134135
format: "month-day"
136+
MyDuration:
137+
type: number
138+
format: "duration"
135139
MyObj:
136140
type: object
137141
properties:
@@ -172,6 +176,9 @@ components:
172176
monthDay:
173177
type: string
174178
format: month-day
179+
duration:
180+
type: number
181+
format: duration
175182
```
176183
177184
Smithy:
@@ -198,6 +205,8 @@ use alloy#ZoneId
198205
use alloy#zoneIdFormat
199206
use alloy#ZoneOffset
200207
use alloy#zoneOffsetFormat
208+
use alloy#Duration
209+
use alloy#durationSecondsFormat
201210

202211
structure MyObj {
203212
myTimestamp: MyTimestamp
@@ -213,6 +222,7 @@ structure MyObj {
213222
year: Year
214223
yearMonth: YearMonth
215224
monthDay: MonthDay
225+
duration: Duration
216226
}
217227

218228
@dateFormat
@@ -251,6 +261,9 @@ string MyZoneId
251261

252262
@zoneOffsetFormat
253263
string MyZoneOffset
264+
265+
@durationSecondsFormat
266+
bigDecimal MyDuration
254267
```
255268

256269
#### Aggregate Shapes

modules/json-schema/src/internals/Extractors.scala

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -162,24 +162,21 @@ private[json_schema] object Extractors {
162162
// I:
163163
// type: integer
164164
// format: year
165+
// I:
166+
// type: number
167+
// format: duration
165168
// The json schema parser treats any integer type with a format fields as a CombinedSchema of StringSchema and NumberSchema
166169
// where the StringSchema has the format set
167170
case (combinedSchema: CombinedSchema) => {
168171
val subschemas = combinedSchema.getSubschemas().asScala.toSet
169172

170-
val isNumberSchema = subschemas.exists {
171-
case (_: NumberSchema) => true
172-
case _ => false
173-
}
174-
val hasYearFormat = subschemas.exists {
175-
case Format("year") => true
176-
case _ => false
177-
}
178-
179-
if (isNumberSchema && hasYearFormat) {
180-
Some(List.empty -> PYear)
181-
} else
182-
None
173+
for {
174+
_ <- subschemas.collectFirst { case (x: NumberSchema) => Some(x) }
175+
format <- subschemas.collectFirst {
176+
case Format("year") => PYear
177+
case Format("duration") => PDuration
178+
}
179+
} yield List.empty -> format
183180
}
184181

185182
// S:

modules/json-schema/src/internals/LoadSchema.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ private[compiler] object LoadSchema extends (JSONObject => Schema) {
4040
.addFormatValidator(new EmptyValidator("year"))
4141
.addFormatValidator(new EmptyValidator("year-month"))
4242
.addFormatValidator(new EmptyValidator("month-day"))
43+
.addFormatValidator(new EmptyValidator("duration"))
4344
.useDefaults(true)
4445
.schemaJson(sch)
4546
.build()

modules/json-schema/test/src/TimeTypeSpec.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ final class TimeTypeSpec extends munit.FunSuite {
8989
"@alloy#monthDayFormat"
9090
)
9191
}
92+
93+
test("duration newtype definition") {
94+
runNewtypeTest(
95+
"duration",
96+
List("@alloy#durationSecondsFormat"),
97+
"number",
98+
"bigDecimal"
99+
)
100+
}
92101

93102
test("nested definitions") {
94103
val jsonSchString =
@@ -141,6 +150,10 @@ final class TimeTypeSpec extends munit.FunSuite {
141150
| "monthDay": {
142151
| "type": "string",
143152
| "format": "month-day"
153+
| },
154+
| "duration": {
155+
| "type": "number",
156+
| "format": "duration"
144157
| }
145158
| }
146159
|}
@@ -160,6 +173,7 @@ final class TimeTypeSpec extends munit.FunSuite {
160173
| year: alloy#Year
161174
| yearMonth: alloy#YearMonth
162175
| monthDay: alloy#MonthDay
176+
| duration: alloy#Duration
163177
|}
164178
|""".stripMargin
165179

0 commit comments

Comments
 (0)