diff --git a/pkg/cmd/template/cmd.go b/pkg/cmd/template/cmd.go index 713fa241..e4e932b3 100644 --- a/pkg/cmd/template/cmd.go +++ b/pkg/cmd/template/cmd.go @@ -146,7 +146,7 @@ func (o *Options) RunWithFiles(in Input, ui ui.UI) Output { if err != nil { return Output{Err: err} } - if schemaType == RegularFilesOutputTypeOpenAPI { + if schemaType == RegularFilesOutputTypeOpenAPI || schemaType == RegularFilesOutputTypeJSONSchema { return Output{Err: fmt.Errorf("Output type currently only supported for data values schema (i.e. include --data-values-schema-inspect)")} } @@ -190,8 +190,16 @@ func (o *Options) inspectSchema(dataValuesSchema *datavalues.Schema) Output { }, } } - return Output{Err: fmt.Errorf("Data values schema export only supported in OpenAPI v3 format; specify format with --output=%s flag", - RegularFilesOutputTypeOpenAPI)} + if format == RegularFilesOutputTypeJSONSchema { + jsonSchemaDoc := schema.NewJSONSchemaDocument(dataValuesSchema.GetDocumentType()) + return Output{ + DocSet: &yamlmeta.DocumentSet{ + Items: []*yamlmeta.Document{jsonSchemaDoc.AsDocument()}, + }, + } + } + return Output{Err: fmt.Errorf("Data values schema export only supported in OpenAPI v3 and JSON Schema format; specify format with --output=(%s|%s) flag", + RegularFilesOutputTypeOpenAPI, RegularFilesOutputTypeJSONSchema)} } func (o *Options) pickSource(srcs []FileSource, pickFunc func(FileSource) bool) FileSource { diff --git a/pkg/cmd/template/regular_input.go b/pkg/cmd/template/regular_input.go index 2d08a866..167c4243 100644 --- a/pkg/cmd/template/regular_input.go +++ b/pkg/cmd/template/regular_input.go @@ -134,14 +134,15 @@ const ( // When the FileSource are RegularFilesSource, indicates which schema type to use when rendering the output. const ( - RegularFilesOutputTypeOpenAPI = "openapi-v3" - RegularFilesOutputTypeNone = "" + RegularFilesOutputTypeOpenAPI = "openapi-v3" + RegularFilesOutputTypeJSONSchema = "json-schema" + RegularFilesOutputTypeNone = "" ) // Collections of each category of output type var ( RegularFilesOutputFormatTypes = []string{RegularFilesOutputTypeYAML, RegularFilesOutputTypeJSON, RegularFilesOutputTypePos} - RegularFilesOutputSchemaTypes = []string{RegularFilesOutputTypeOpenAPI} + RegularFilesOutputSchemaTypes = []string{RegularFilesOutputTypeOpenAPI, RegularFilesOutputTypeJSONSchema} RegularFilesOutputTypes = append(RegularFilesOutputFormatTypes, RegularFilesOutputSchemaTypes...) ) diff --git a/pkg/cmd/template/schema_inspect_test.go b/pkg/cmd/template/schema_inspect_test.go index 2e89d538..d5d3374e 100644 --- a/pkg/cmd/template/schema_inspect_test.go +++ b/pkg/cmd/template/schema_inspect_test.go @@ -1125,7 +1125,7 @@ components: } func TestSchemaInspect_errors(t *testing.T) { - t.Run("when --output is anything other than 'openapi-v3'", func(t *testing.T) { + t.Run("when --output is anything other than 'openapi-v3' or 'json-schema", func(t *testing.T) { opts := cmdtpl.NewOptions() opts.DataValuesFlags.InspectSchema = true @@ -1133,7 +1133,7 @@ func TestSchemaInspect_errors(t *testing.T) { --- foo: doesn't matter ` - expectedErr := "Data values schema export only supported in OpenAPI v3 format; specify format with --output=openapi-v3 flag" + expectedErr := "Data values schema export only supported in OpenAPI v3 and JSON Schema format; specify format with --output=(openapi-v3|json-schema) flag" filesToProcess := files.NewSortedFiles([]*files.File{ files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), @@ -1142,7 +1142,7 @@ foo: doesn't matter assertFails(t, filesToProcess, expectedErr, opts) }) - t.Run("when --output is set to 'openapi-v3' but not inspecting schema", func(t *testing.T) { + t.Run("when --output is set but not inspecting schema", func(t *testing.T) { opts := cmdtpl.NewOptions() opts.DataValuesFlags.InspectSchema = false opts.RegularFilesSourceOpts.OutputType.Types = []string{"openapi-v3"} @@ -1161,6 +1161,724 @@ foo: doesn't matter }) } +func TestSchemaInspect_exports_an_JSONschema_doc(t *testing.T) { + t.Run("for all inferred types with their inferred defaults", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + int_key: 10 + bool_key: true + false_key: false + string_key: some text + float_key: 9.1 + array_of_scalars: + - "" + array_of_maps: + - foo: "" + bar: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + int_key: + type: integer + default: 10 + bool_key: + type: boolean + default: true + false_key: + type: boolean + default: false + string_key: + type: string + default: some text + float_key: + type: number + format: float + default: 9.1 + array_of_scalars: + type: array + items: + type: string + default: "" + default: [] + array_of_maps: + type: array + items: + type: object + additionalProperties: false + properties: + foo: + type: string + default: "" + bar: + type: string + default: "" + default: [] +` + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("including explicitly set default values", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + #@schema/default 10 + int_key: 0 + #@schema/default True + bool_key: false + #@schema/default False + false_key: true + #@schema/default "some text" + string_key: "" + #@schema/default 9.1 + float_key: 0.0 + #@schema/default [1,2,3] + array_of_scalars: + - 0 + #@schema/default [{"bar": "thing 1"},{"bar": "thing 2"}, {"bar": "thing 3"}] + array_of_maps: + - bar: "" + ree: "default" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + int_key: + type: integer + default: 10 + bool_key: + type: boolean + default: true + false_key: + type: boolean + default: false + string_key: + type: string + default: some text + float_key: + type: number + format: float + default: 9.1 + array_of_scalars: + type: array + items: + type: integer + default: 0 + default: + - 1 + - 2 + - 3 + array_of_maps: + type: array + items: + type: object + additionalProperties: false + properties: + bar: + type: string + default: "" + ree: + type: string + default: default + default: + - bar: thing 1 + ree: default + - bar: thing 2 + ree: default + - bar: thing 3 + ree: default +` + + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("including nullable values", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + #@schema/nullable + int_key: 0 + #@schema/nullable + bool_key: false + #@schema/nullable + false_key: true + #@schema/nullable + string_key: "" + #@schema/nullable + float_key: 0.0 + #@schema/nullable + array_of_scalars: + - 0 + #@schema/nullable + array_of_maps: + - + #@schema/nullable + bar: "" + #@schema/nullable + ree: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + int_key: + type: + - integer + - "null" + default: null + bool_key: + type: + - boolean + - "null" + default: null + false_key: + type: + - boolean + - "null" + default: null + string_key: + type: + - string + - "null" + default: null + float_key: + type: + - number + - "null" + format: float + default: null + array_of_scalars: + type: + - array + - "null" + items: + type: integer + default: 0 + default: null + array_of_maps: + type: + - array + - "null" + items: + type: object + additionalProperties: false + properties: + bar: + type: + - string + - "null" + default: null + ree: + type: + - string + - "null" + default: null + default: null +` + + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("including 'any' values", func(t *testing.T) { + t.Run("on documents", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +#@schema/type any=True +--- +foo: + int_key: 0 + array_of_scalars: + - "" + array_of_maps: + - foo: "" + bar: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: +- "null" +- string +- number +- object +- array +- boolean +default: + foo: + int_key: 0 + array_of_scalars: + - "" + array_of_maps: + - foo: "" + bar: "" +` + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("on map items", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +#@schema/type any=True +foo: + int_key: 0 + array_of_scalars: + - "" + array_of_maps: + - foo: "" + bar: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: + - "null" + - string + - number + - object + - array + - boolean + default: + int_key: 0 + array_of_scalars: + - "" + array_of_maps: + - foo: "" + bar: "" +` + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("on array items", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + int_key: 0 + array_of_scalars: + #@schema/type any=True + - "" + array_of_maps: + - foo: "" + bar: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + int_key: + type: integer + default: 0 + array_of_scalars: + type: array + items: + type: + - "null" + - string + - number + - object + - array + - boolean + default: "" + default: [] + array_of_maps: + type: array + items: + type: object + additionalProperties: false + properties: + foo: + type: string + default: "" + bar: + type: string + default: "" + default: [] +` + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + }) + t.Run("including nullable values with defaults", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + #@schema/default 10 + #@schema/nullable + int_key: 0 + + #@schema/default True + #@schema/nullable + bool_key: false + + #@schema/nullable + #@schema/default False + false_key: true + + #@schema/nullable + #@schema/default "some text" + string_key: "" + + #@schema/nullable + #@schema/default 9.1 + float_key: 0.0 + + #@schema/nullable + #@schema/default [1,2,3] + array_of_scalars: + - 0 + + #@schema/default [{"bar": "thing 1"},{"bar": "thing 2"}, {"bar": "thing 3"}] + #@schema/nullable + array_of_maps: + - + #@schema/nullable + bar: "" + #@schema/nullable + ree: "" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + int_key: + type: + - integer + - "null" + default: 10 + bool_key: + type: + - boolean + - "null" + default: true + false_key: + type: + - boolean + - "null" + default: false + string_key: + type: + - string + - "null" + default: some text + float_key: + type: + - number + - "null" + format: float + default: 9.1 + array_of_scalars: + type: + - array + - "null" + items: + type: integer + default: 0 + default: + - 1 + - 2 + - 3 + array_of_maps: + type: + - array + - "null" + items: + type: object + additionalProperties: false + properties: + bar: + type: + - string + - "null" + default: null + ree: + type: + - string + - "null" + default: null + default: + - bar: thing 1 + ree: null + - bar: thing 2 + ree: null + - bar: thing 3 + ree: null +` + + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + t.Run("including named validations", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + #@schema/default 10 + #@schema/validation min=0, max=100 + range_key: 0 + + #@schema/validation min=-1.1, max=100.1 + range_float_key: 2.2 + + #@schema/default 10 + #@schema/validation min=0 + min_key: 0 + + #@schema/default 10 + #@schema/validation max=100 + max_key: 0 + + #@schema/validation min_len=1, max_len=10 + string_key: "" + + #@schema/validation min_len=3, max_len=4 + array_key: + - "" + + #@schema/validation min_len=2, max_len=5 + map_key: {} + + #@schema/validation one_of=[1,2,3] + one_of_integers: 1 + + #@schema/validation one_of=["one", "two", "three"] + one_of_strings: "one" + + #@schema/type any=True + #@schema/validation one_of=["one", 2, 3.3, {}] + one_of_mixed: "one" +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + range_key: + type: integer + default: 10 + minimum: 0 + maximum: 100 + range_float_key: + type: number + format: float + default: 2.2 + minimum: -1.1 + maximum: 100.1 + min_key: + type: integer + default: 10 + minimum: 0 + max_key: + type: integer + default: 10 + maximum: 100 + string_key: + type: string + default: "" + minLength: 1 + maxLength: 10 + array_key: + type: array + items: + type: string + default: "" + default: [] + minItems: 3 + maxItems: 4 + map_key: + type: object + additionalProperties: false + properties: {} + minProperties: 2 + maxProperties: 5 + one_of_integers: + type: integer + default: 1 + enum: + - 1 + - 2 + - 3 + one_of_strings: + type: string + default: one + enum: + - one + - two + - three + one_of_mixed: + type: + - "null" + - string + - number + - object + - array + - boolean + default: one + enum: + - one + - 2 + - 3.3 + - {} +` + + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) + + t.Run("not including named validations when when= is present", func(t *testing.T) { + opts := cmdtpl.NewOptions() + opts.DataValuesFlags.InspectSchema = true + opts.RegularFilesSourceOpts.OutputType.Types = []string{"json-schema"} + + schemaYAML := `#@data/values-schema +--- +foo: + #@schema/validation min=0, max=100, when=lambda: False + range_key: 0 + + #@schema/default 10 + #@schema/validation min=0, when=lambda: False + min_key: 0 + + #@schema/default 10 + #@schema/validation max=100, when=lambda: False + max_key: 0 + + #@schema/validation min_len=1, max_len=10, when=lambda: False + string_key: "" + + #@schema/validation one_of=[1,2,3], when=lambda: False + one_of_integers: 1 +` + expected := `$schema: https://json-schema.org/draft/2020-12/schema +$id: https://example.biz/schema/ytt/data-values.json +description: Schema for data values, generated by ytt +type: object +additionalProperties: false +properties: + foo: + type: object + additionalProperties: false + properties: + range_key: + type: integer + default: 0 + min_key: + type: integer + default: 10 + max_key: + type: integer + default: 10 + string_key: + type: string + default: "" + one_of_integers: + type: integer + default: 1 +` + + filesToProcess := files.NewSortedFiles([]*files.File{ + files.MustNewFileFromSource(files.NewBytesSource("schema.yml", []byte(schemaYAML))), + }) + + assertSucceedsDocSet(t, filesToProcess, expected, opts) + }) +} + func assertSucceedsDocSet(t *testing.T, filesToProcess []*files.File, expectedOut string, opts *cmdtpl.Options) { t.Helper() out := opts.RunWithFiles(cmdtpl.Input{Files: filesToProcess}, ui.NewTTY(false)) diff --git a/pkg/schema/jsonschema.go b/pkg/schema/jsonschema.go new file mode 100644 index 00000000..f2387655 --- /dev/null +++ b/pkg/schema/jsonschema.go @@ -0,0 +1,148 @@ +// Copyright 2024 The Carvel Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "fmt" + "sort" + + "carvel.dev/ytt/pkg/yamlmeta" +) + +// JSONSchemaDocument holds the document type used for creating an JSON Schema document +type JSONSchemaDocument struct { + OpenAPIDocument +} + +// NewJSONSchemaDocument creates an instance of an OpenAPIDocument based on the given DocumentType +func NewJSONSchemaDocument(docType *DocumentType) *JSONSchemaDocument { + return &JSONSchemaDocument{*NewOpenAPIDocument(docType)} +} + +// AsDocument generates a new AST of this OpenAPI v3.0.x document, populating the `schemas:` section with the +// type information contained in `docType`. +func (j *JSONSchemaDocument) AsDocument() *yamlmeta.Document { + jsonSchemaProperties := j.calculateProperties(j.docType) + + jsonSchemaProperties.Items = append( + []*yamlmeta.MapItem{ + {Key: "$schema", Value: "https://json-schema.org/draft/2020-12/schema"}, + {Key: "$id", Value: "https://example.biz/schema/ytt/data-values.json"}, + {Key: "description", Value: "Schema for data values, generated by ytt"}, + }, + jsonSchemaProperties.Items..., + ) + + return &yamlmeta.Document{Value: jsonSchemaProperties} +} + +func (j *JSONSchemaDocument) calculateProperties(schemaVal interface{}) *yamlmeta.Map { + switch typedValue := schemaVal.(type) { + case *DocumentType: + result := j.calculateProperties(typedValue.GetValueType()) + result.Items = append(result.Items, j.convertValidations(typedValue)...) + sort.Sort(openAPIKeys(result.Items)) + return result + + case *MapType: + var items openAPIKeys + items = append(items, j.collectDocumentation(typedValue)...) + items = append(items, j.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: "object"}) + items = append(items, &yamlmeta.MapItem{Key: additionalPropsProp, Value: false}) + + var properties []*yamlmeta.MapItem + for _, i := range typedValue.Items { + mi := yamlmeta.MapItem{Key: i.Key, Value: j.calculateProperties(i)} + properties = append(properties, &mi) + } + items = append(items, &yamlmeta.MapItem{Key: propertiesProp, Value: &yamlmeta.Map{Items: properties}}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *MapItemType: + result := j.calculateProperties(typedValue.GetValueType()) + result.Items = append(result.Items, j.convertValidations(typedValue)...) + sort.Sort(openAPIKeys(result.Items)) + return result + + case *ArrayType: + var items openAPIKeys + items = append(items, j.collectDocumentation(typedValue)...) + items = append(items, j.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: "array"}) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + valueType := typedValue.GetValueType().(*ArrayItemType) + properties := j.calculateProperties(valueType.GetValueType()) + items = append(items, &yamlmeta.MapItem{Key: itemsProp, Value: properties}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *ScalarType: + var items openAPIKeys + items = append(items, j.collectDocumentation(typedValue)...) + items = append(items, j.convertValidations(typedValue)...) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + typeString := j.openAPITypeFor(typedValue) + items = append(items, &yamlmeta.MapItem{Key: typeProp, Value: typeString}) + + if typedValue.String() == "float" { + items = append(items, &yamlmeta.MapItem{Key: formatProp, Value: "float"}) + } + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *NullType: + var items openAPIKeys + items = append(items, j.collectDocumentation(typedValue)...) + items = append(items, j.convertValidations(typedValue)...) + + properties := j.calculateProperties(typedValue.GetValueType()) + // we need to append the "null" type to the list of types + for i := 0; i < len(properties.Items); i++ { + if properties.Items[i].Key == "type" { + // this is a map item with a single valeu, we now need to convert it to an array + typeItem := properties.Items[i] + nullableItem := &yamlmeta.MapItem{Key: "type", Value: &yamlmeta.Array{Items: []*yamlmeta.ArrayItem{ + {Value: typeItem.Value}, // this is the original type + {Value: "null"}, + }}} + + items = append(items, nullableItem) + } else { + items = append(items, properties.Items[i]) + } + } + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + + case *AnyType: + var items openAPIKeys + items = append(items, j.collectDocumentation(typedValue)...) + items = append(items, j.convertValidations(typedValue)...) + // AnyType must allow all value types, and need to explicitly list them for json schema + items = append(items, &yamlmeta.MapItem{Key: typeProp, + Value: &yamlmeta.Array{Items: []*yamlmeta.ArrayItem{ + {Value: "null"}, + {Value: "string"}, + {Value: "number"}, + {Value: "object"}, + {Value: "array"}, + {Value: "boolean"}, + }}, + }) + items = append(items, &yamlmeta.MapItem{Key: defaultProp, Value: typedValue.GetDefaultValue()}) + + sort.Sort(items) + return &yamlmeta.Map{Items: items} + default: + panic(fmt.Sprintf("Unrecognized type %T", schemaVal)) + } +}