diff --git a/encoding/jsonschema/decode.go b/encoding/jsonschema/decode.go index 84d7ed82a..c644ff084 100644 --- a/encoding/jsonschema/decode.go +++ b/encoding/jsonschema/decode.go @@ -34,19 +34,10 @@ import ( const rootDefs = "def" -func decode(filename string, inst *cue.Instance) (*ast.File, errors.Error) { - d := &decoder{ - imports: map[string]*ast.Ident{}, - } - e := d.decode(filename, inst) - if d.errs != nil { - return nil, d.errs - } - return e, nil -} - // A decoder converts JSON schema to CUE. type decoder struct { + cfg *Config + errs errors.Error imports map[string]*ast.Ident @@ -63,12 +54,13 @@ func (d *decoder) addImport(pkg string) *ast.Ident { return ident } -func (d *decoder) decode(filename string, inst *cue.Instance) *ast.File { +func (d *decoder) decode(inst *cue.Instance) *ast.File { root := state{decoder: d} expr, state := root.schemaState(inst.Value()) var a []ast.Decl + filename := d.cfg.ID name := filepath.ToSlash(filename) if state.id != "" { name = strings.Trim(name, "#") diff --git a/encoding/jsonschema/decode_test.go b/encoding/jsonschema/decode_test.go index da64a24ef..dddb12754 100644 --- a/encoding/jsonschema/decode_test.go +++ b/encoding/jsonschema/decode_test.go @@ -75,8 +75,7 @@ func TestDecode(t *testing.T) { t.Fatal(err) } - // TODO: use actual API. - expr, err := decode(fullpath, in) + expr, err := Extract(in, &Config{ID: fullpath}) if err != nil && errout == nil { t.Fatal(errors.Details(err, nil)) } diff --git a/encoding/jsonschema/jsonschema.go b/encoding/jsonschema/jsonschema.go new file mode 100644 index 000000000..8c496e690 --- /dev/null +++ b/encoding/jsonschema/jsonschema.go @@ -0,0 +1,64 @@ +// Copyright 2020 CUE Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package jsonschema implements the JSON schema standard. +// +// Mapping and Linking +// +// JSON Schema are often defined in a single file. CUE, on the other hand +// idomatically defines schema as a definition. +// +// CUE: +// $schema: which schema is used for validation. +// $id: which validation does this schema provide. +// +// Foo: _ @jsonschema(sc) +// @source(https://...) // What schema is used to validate. +// +// NOTE: JSON Schema is a draft standard and may undergo backwards incompatible +// changes. +package jsonschema + +import ( + "cuelang.org/go/cue" + "cuelang.org/go/cue/ast" +) + +// Extract converts JSON Schema data into an equivalent CUE representation. +// +// The generated CUE schema is guaranteed to deem valid any value that is +// a valid instance of the source JSON schema. +func Extract(data *cue.Instance, cfg *Config) (*ast.File, error) { + d := &decoder{ + cfg: cfg, + imports: map[string]*ast.Ident{}, + } + e := d.decode(data) + if d.errs != nil { + return nil, d.errs + } + return e, nil +} + +// A Config configures a JSON Schema encoding or decoding. +type Config struct { + ID string // URL of the original source, corresponding to the $id field. + + // TODO: configurability to make it compatible with OpenAPI, such as + // - locations of definitions: #/components/schemas, for instance. + // - selection and definition of formats + // - documentation hooks. + + _ struct{} // prohibit casting from different type. +}