internal/filetypes: add auto interpretation
- automatically detect OpenAPI and JSONSchema
based on strict criteria.
- json+schema no longer magically maps to jsonschema
For inputs, auto mode is now automatically enabled for .json
and .yaml/yml files. Any explicit tag, like json: or data: disables
auto mode.
Change-Id: I391179c4542b823c428e4989e31381e00caa4a45
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5410
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/internal/encoding/encoding.go b/internal/encoding/encoding.go
index 83de8a3..14d579b 100644
--- a/internal/encoding/encoding.go
+++ b/internal/encoding/encoding.go
@@ -45,7 +45,7 @@
cfg *Config
closer io.Closer
next func() (ast.Expr, error)
- interpret func(*cue.Instance) (file *ast.File, id string, err error)
+ interpret interpretFunc
expr ast.Expr
file *ast.File
filename string // may change on iteration for some formats
@@ -54,6 +54,8 @@
err error
}
+type interpretFunc func(*cue.Instance) (file *ast.File, id string, err error)
+
// ID returns a canonical identifier for the decoded object or "" if no such
// identifier could be found.
func (i *Decoder) ID() string {
@@ -69,6 +71,7 @@
return
}
// Decoder level
+ i.file = nil
i.expr, i.err = i.next()
i.index++
if i.err != nil {
@@ -77,7 +80,8 @@
// Interpretations
if i.interpret != nil {
var r cue.Runtime
- inst, err := r.CompileFile(i.File())
+ i.file = i.File()
+ inst, err := r.CompileFile(i.file)
if err != nil {
i.err = err
return
@@ -176,33 +180,22 @@
switch f.Interpretation {
case "":
+ case build.Auto:
+ openAPI := openAPIFunc(cfg, f)
+ jsonSchema := jsonSchemaFunc(cfg, f)
+ i.interpret = func(inst *cue.Instance) (file *ast.File, id string, err error) {
+ switch Detect(inst.Value()) {
+ case build.JSONSchema:
+ return jsonSchema(inst)
+ case build.OpenAPI:
+ return openAPI(inst)
+ }
+ return i.file, "", i.err
+ }
case build.OpenAPI:
- i.interpret = func(i *cue.Instance) (file *ast.File, id string, err error) {
- cfg := &openapi.Config{PkgName: cfg.PkgName}
- file, err = simplify(openapi.Extract(i, cfg))
- return file, "", err
- }
+ i.interpret = openAPIFunc(cfg, f)
case build.JSONSchema:
- i.interpret = func(i *cue.Instance) (file *ast.File, id string, err error) {
- id = f.Tags["id"]
- if id == "" {
- id, _ = i.Lookup("$id").String()
- }
- if id != "" {
- u, err := url.Parse(id)
- if err != nil {
- return nil, "", errors.Wrapf(err, token.NoPos, "invalid id")
- }
- u.Scheme = ""
- id = strings.TrimPrefix(u.String(), "//")
- }
- cfg := &jsonschema.Config{
- ID: id,
- PkgName: cfg.PkgName,
- }
- file, err = simplify(jsonschema.Extract(i, cfg))
- return file, id, err
- }
+ i.interpret = jsonSchemaFunc(cfg, f)
default:
i.err = fmt.Errorf("unsupported interpretation %q", f.Interpretation)
}
@@ -237,6 +230,37 @@
return i
}
+func jsonSchemaFunc(cfg *Config, f *build.File) interpretFunc {
+ return func(i *cue.Instance) (file *ast.File, id string, err error) {
+ id = f.Tags["id"]
+ if id == "" {
+ id, _ = i.Lookup("$id").String()
+ }
+ if id != "" {
+ u, err := url.Parse(id)
+ if err != nil {
+ return nil, "", errors.Wrapf(err, token.NoPos, "invalid id")
+ }
+ u.Scheme = ""
+ id = strings.TrimPrefix(u.String(), "//")
+ }
+ cfg := &jsonschema.Config{
+ ID: id,
+ PkgName: cfg.PkgName,
+ }
+ file, err = simplify(jsonschema.Extract(i, cfg))
+ return file, id, err
+ }
+}
+
+func openAPIFunc(c *Config, f *build.File) interpretFunc {
+ cfg := &openapi.Config{PkgName: c.PkgName}
+ return func(i *cue.Instance) (file *ast.File, id string, err error) {
+ file, err = simplify(openapi.Extract(i, cfg))
+ return file, "", err
+ }
+}
+
func reader(f *build.File, stdin io.Reader) (io.ReadCloser, error) {
switch s := f.Source.(type) {
case nil: