blob: 3da88caf96e1111309c0c7289da13ab65c71a0d2 [file] [log] [blame]
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -04001// Copyright 2019 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package openapi
16
17import (
18 "encoding/json"
19
20 "cuelang.org/go/cue"
21)
22
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020023// A Generator converts CUE to OpenAPI.
24type Generator struct {
Marcel van Lohuizen4de93e12019-07-02 20:04:10 +020025 // Info specifies the info section of the OpenAPI document. To be a valid
26 // OpenAPI document, it must include at least the title and version fields.
27 Info OrderedMap
28
Marcel van Lohuizenef90d5c2019-06-29 14:05:25 +020029 // ReferenceFunc allows users to specify an alternative representation
Marcel van Lohuizenceb003d2019-08-08 13:45:10 +020030 // for references. An empty string tells the generator to expand the type
Marcel van Lohuizen35abfa72019-08-12 15:31:53 +020031 // in place and, if applicable, not generate a schema for that entity.
Marcel van Lohuizenef90d5c2019-06-29 14:05:25 +020032 ReferenceFunc func(inst *cue.Instance, path []string) string
33
Marcel van Lohuizen4de93e12019-07-02 20:04:10 +020034 // DescriptionFunc allows rewriting a description associated with a certain
35 // field. A typical implementation compiles the description from the
36 // comments obtains from the Doc method. No description field is added if
37 // the empty string is returned.
38 DescriptionFunc func(v cue.Value) string
39
Marcel van Lohuizenef90d5c2019-06-29 14:05:25 +020040 // SelfContained causes all non-expanded external references to be included
41 // in this document.
42 SelfContained bool
43
Marcel van Lohuizen7b7ccdd2019-07-03 13:33:03 +020044 // FieldFilter defines a regular expression of all fields to omit from the
45 // output. It is only allowed to filter fields that add additional
46 // constraints. Fields that indicate basic types cannot be removed. It is
47 // an error for such fields to be excluded by this filter.
48 // Fields are qualified by their Object type. For instance, the
49 // minimum field of the schema object is qualified as Schema/minimum.
50 FieldFilter string
51
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -040052 // ExpandReferences replaces references with actual objects when generating
Marcel van Lohuizen73e3f6b2019-08-01 16:10:57 +020053 // OpenAPI Schema. It is an error for an CUE value to refer to itself
54 // if this option is used.
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -040055 ExpandReferences bool
56}
57
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020058// Config is now Generator
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020059type Config = Generator
60
61// Gen generates the set OpenAPI schema for all top-level types of the
62// given instance.
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -040063func Gen(inst *cue.Instance, c *Config) ([]byte, error) {
64 if c == nil {
65 c = defaultConfig
66 }
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020067 all, err := c.All(inst)
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -040068 if err != nil {
69 return nil, err
70 }
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020071 return json.Marshal(all)
72}
73
74// All generates an OpenAPI definition from the given instance.
75//
76// Note: only a limited number of top-level types are supported so far.
Marcel van Lohuizenc89f5a62019-07-04 10:41:18 +020077func (g *Generator) All(inst *cue.Instance) (*OrderedMap, error) {
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020078 all, err := g.Schemas(inst)
79 if err != nil {
80 return nil, err
81 }
82
83 schemas := &OrderedMap{}
Marcel van Lohuizen0a975332019-07-04 10:43:25 +020084 schemas.Set("schemas", all)
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020085
Marcel van Lohuizenc89f5a62019-07-04 10:41:18 +020086 top := &OrderedMap{}
87 top.Set("openapi", "3.0.0")
88 top.Set("info", &g.Info)
89 top.Set("components", schemas)
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020090
91 return top, nil
92}
93
94// Schemas extracts component/schemas from the CUE top-level types.
Marcel van Lohuizenc89f5a62019-07-04 10:41:18 +020095func (g *Generator) Schemas(inst *cue.Instance) (*OrderedMap, error) {
Marcel van Lohuizen865f1592019-07-02 19:43:45 +020096 comps, err := schemas(g, inst)
97 if err != nil {
98 return nil, err
99 }
100 return comps, err
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -0400101}
102
103var defaultConfig = &Config{}
104
105// TODO
106// The conversion interprets @openapi(<entry> {, <entry>}) attributes as follows:
107//
108// readOnly sets the readOnly flag for a property in the schema
109// only one of readOnly and writeOnly may be set.
110// writeOnly sets the writeOnly flag for a property in the schema
111// only one of readOnly and writeOnly may be set.
112// discriminator explicitly sets a field as the discriminator field
Marcel van Lohuizenf4d483e2019-05-20 08:03:10 -0400113//