encoding/openapi: support time types
Also recognize unsupported builtins for
their type.
Issue #56
Change-Id: Ic900829144d0130db412c1202f82df4e3a56c236
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2724
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/openapi/build.go b/encoding/openapi/build.go
index fa74d5b..bcb21d4 100644
--- a/encoding/openapi/build.go
+++ b/encoding/openapi/build.go
@@ -209,7 +209,7 @@
count := 0
disallowDefault := false
var values cue.Value
- if b.ctx.expandRefs {
+ if b.ctx.expandRefs || b.format != "" {
// Cycles are not allowed when expanding references. Right now we just
// cap the depth of evaluation at 30.
// TODO: do something more principled.
@@ -760,7 +760,6 @@
}
case cue.NoOp, cue.SelectorOp:
- // TODO: determine formats from specific types.
case cue.CallOp:
name := fmt.Sprint(a[0])
diff --git a/encoding/openapi/openapi_test.go b/encoding/openapi/openapi_test.go
index 9fbe314..bcdaf19 100644
--- a/encoding/openapi/openapi_test.go
+++ b/encoding/openapi/openapi_test.go
@@ -63,6 +63,10 @@
"nums.json",
defaultConfig,
}, {
+ "builtins.cue",
+ "builtins.json",
+ defaultConfig,
+ }, {
"oneof.cue",
"oneof.json",
defaultConfig,
diff --git a/encoding/openapi/testdata/builtins.cue b/encoding/openapi/testdata/builtins.cue
new file mode 100644
index 0000000..0d094e4
--- /dev/null
+++ b/encoding/openapi/testdata/builtins.cue
@@ -0,0 +1,22 @@
+import (
+ "time"
+ "list"
+)
+
+_time = time
+
+MyStruct: {
+ timestamp1?: time.Time
+ timestamp2?: time.Time()
+ timestamp3?: time.Format(time.RFC3339Nano)
+ timestamp4?: _time.Time
+ date1?: time.Format(time.RFC3339Date)
+ date2?: _time.Format(time.RFC3339Date)
+
+ // This is not an OpenAPI type and has no format. In this case
+ // we map to a type so that it can be documented properly (without
+ // repeating it).
+ timeout?: time.Duration
+
+ contains: list.Contains("foo") // not supported, but should be recognized as list
+}
diff --git a/encoding/openapi/testdata/builtins.json b/encoding/openapi/testdata/builtins.json
new file mode 100644
index 0000000..1442f6c
--- /dev/null
+++ b/encoding/openapi/testdata/builtins.json
@@ -0,0 +1,50 @@
+{
+ "openapi": "3.0.0",
+ "info": {},
+ "components": {
+ "schemas": {
+ "MyStruct": {
+ "type": "object",
+ "required": [
+ "contains"
+ ],
+ "properties": {
+ "timestamp1": {
+ "type": "string",
+ "format": "dateTime"
+ },
+ "timestamp2": {
+ "type": "string",
+ "format": "dateTime"
+ },
+ "timestamp3": {
+ "type": "string",
+ "format": "dateTime"
+ },
+ "timestamp4": {
+ "type": "string",
+ "format": "dateTime"
+ },
+ "date1": {
+ "type": "string",
+ "format": "date"
+ },
+ "date2": {
+ "type": "string",
+ "format": "date"
+ },
+ "timeout": {
+ "$ref": "#/components/schemas/Duration"
+ },
+ "contains": {
+ "type": "array"
+ }
+ }
+ },
+ "Duration": {
+ "description": "This is not an OpenAPI type and has no format. In this case\nwe map to a type so that it can be documented properly (without\nrepeating it).",
+ "type": "string"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/encoding/openapi/types.go b/encoding/openapi/types.go
index 3995055..e30a4ba 100644
--- a/encoding/openapi/types.go
+++ b/encoding/openapi/types.go
@@ -15,6 +15,8 @@
package openapi
import (
+ "fmt"
+
"github.com/cockroachdb/apd/v2"
"cuelang.org/go/cue"
@@ -32,7 +34,15 @@
"string": "string",
"bytes": "binary",
- // TODO: date, date-time, password.
+ "time.Time": "dateTime",
+ "time.Time ()": "dateTime",
+ `time.Format ("2006-01-02")`: "date",
+
+ // TODO: if a format is more strict (e.g. using zeros instead of nines
+ // for fractional seconds), we could still use this as an approximation.
+ `time.Format ("2006-01-02T15:04:05.999999999Z07:00")`: "dateTime",
+
+ // TODO: password.
}
func extractFormat(v cue.Value) string {
@@ -45,7 +55,11 @@
if err != nil {
return ""
}
- return cueToOpenAPI[string(b)]
+ if s, ok := cueToOpenAPI[string(b)]; ok {
+ return s
+ }
+ s := fmt.Sprint(v)
+ return cueToOpenAPI[s]
}
func simplify(b *builder, t *OrderedMap) {