mirror of https://github.com/databricks/cli.git
replaced properties and items with schema
This commit is contained in:
parent
cc350f761a
commit
d2f466afc5
|
@ -11,12 +11,13 @@ import (
|
||||||
// TODO: Add required validation for omitempty
|
// TODO: Add required validation for omitempty
|
||||||
// TODO: Add example documentation
|
// TODO: Add example documentation
|
||||||
// TODO: Do final checks for more validation that can be added to json schema
|
// TODO: Do final checks for more validation that can be added to json schema
|
||||||
|
// TODO: Run all tests to see code coverage and add tests for missing assertions
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is a struct to translate golang types into json schema. Here is the mapping
|
This is a struct to translate golang types into json schema. Here is the mapping
|
||||||
between json schema types and golang types
|
between json schema types and golang types
|
||||||
|
|
||||||
- GolangType -> Javascript type / Json Schema
|
- GolangType -> Javascript type / Json Schema2
|
||||||
|
|
||||||
Javascript Primitives:
|
Javascript Primitives:
|
||||||
- bool -> boolean
|
- bool -> boolean
|
||||||
|
@ -24,7 +25,7 @@ import (
|
||||||
- int (all variants) -> number
|
- int (all variants) -> number
|
||||||
- float (all variants) -> number
|
- float (all variants) -> number
|
||||||
|
|
||||||
Json Schema Fields:
|
Json Schema2 Fields:
|
||||||
- map[string]MyStruct -> {
|
- map[string]MyStruct -> {
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: {}
|
additionalProperties: {}
|
||||||
|
@ -46,24 +47,11 @@ import (
|
||||||
for details visit: https://json-schema.org/understanding-json-schema/reference/object.html#properties
|
for details visit: https://json-schema.org/understanding-json-schema/reference/object.html#properties
|
||||||
*/
|
*/
|
||||||
type Schema struct {
|
type Schema struct {
|
||||||
Type JavascriptType `json:"type"`
|
Type JavascriptType `json:"type"`
|
||||||
Properties map[string]*Property `json:"properties,omitempty"`
|
Items *Schema `json:"items,omitempty"`
|
||||||
AdditionalProperties *Property `json:"additionalProperties,omitempty"`
|
Properties map[string]*Schema `json:"properties,omitempty"`
|
||||||
Required []string `json:"required,omitempty"`
|
AdditionalProperties *Schema `json:"additionalProperties,omitempty"`
|
||||||
}
|
Required []string `json:"required,omitempty"`
|
||||||
|
|
||||||
type Property struct {
|
|
||||||
Type JavascriptType `json:"type"`
|
|
||||||
Items *Items `json:"items,omitempty"`
|
|
||||||
Properties map[string]*Property `json:"properties,omitempty"`
|
|
||||||
AdditionalProperties *Property `json:"additionalProperties,omitempty"`
|
|
||||||
Required []string `json:"required,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Items struct {
|
|
||||||
Type JavascriptType `json:"type"`
|
|
||||||
Properties map[string]*Property `json:"properties,omitempty"`
|
|
||||||
Required []string `json:"required,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE about loops in golangType: Right now we error out if there is a loop
|
// NOTE about loops in golangType: Right now we error out if there is a loop
|
||||||
|
@ -75,7 +63,7 @@ type Items struct {
|
||||||
func NewSchema(golangType reflect.Type) (*Schema, error) {
|
func NewSchema(golangType reflect.Type) (*Schema, error) {
|
||||||
seenTypes := map[reflect.Type]struct{}{}
|
seenTypes := map[reflect.Type]struct{}{}
|
||||||
debugTrace := list.New()
|
debugTrace := list.New()
|
||||||
rootProp, err := toProperty(golangType, seenTypes, debugTrace)
|
rootProp, err := toSchema(golangType, seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errWithTrace(err.Error(), debugTrace)
|
return nil, errWithTrace(err.Error(), debugTrace)
|
||||||
}
|
}
|
||||||
|
@ -136,7 +124,7 @@ func errWithTrace(prefix string, trace *list.List) error {
|
||||||
|
|
||||||
// A wrapper over toProperty function with checks for an cycles to avoid being
|
// A wrapper over toProperty function with checks for an cycles to avoid being
|
||||||
// stuck in an loop when traversing the config struct
|
// stuck in an loop when traversing the config struct
|
||||||
func safeToProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Property, error) {
|
func safeToSchema(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
||||||
// detect cycles. Fail if a cycle is detected
|
// detect cycles. Fail if a cycle is detected
|
||||||
_, ok := seenTypes[golangType]
|
_, ok := seenTypes[golangType]
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -145,7 +133,7 @@ func safeToProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}
|
||||||
}
|
}
|
||||||
// Update set of types in current path
|
// Update set of types in current path
|
||||||
seenTypes[golangType] = struct{}{}
|
seenTypes[golangType] = struct{}{}
|
||||||
props, err := toProperty(golangType, seenTypes, debugTrace)
|
props, err := toSchema(golangType, seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -197,11 +185,11 @@ func addStructFields(fields []reflect.StructField, golangType reflect.Type) []re
|
||||||
// Used to identify cycles.
|
// Used to identify cycles.
|
||||||
// debugTrace: linked list of golang types encounted. In case of errors this
|
// debugTrace: linked list of golang types encounted. In case of errors this
|
||||||
// helps log where the error originated from
|
// helps log where the error originated from
|
||||||
func toProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Property, error) {
|
func toSchema(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
||||||
// *Struct and Struct generate identical json schemas
|
// *Struct and Struct generate identical json schemas
|
||||||
// TODO: add test case for pointer
|
// TODO: add test case for pointer
|
||||||
if golangType.Kind() == reflect.Pointer {
|
if golangType.Kind() == reflect.Pointer {
|
||||||
return toProperty(golangType.Elem(), seenTypes, debugTrace)
|
return toSchema(golangType.Elem(), seenTypes, debugTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add test case for interfaces
|
// TODO: add test case for interfaces
|
||||||
|
@ -215,18 +203,18 @@ func toProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, de
|
||||||
}
|
}
|
||||||
|
|
||||||
// case array/slice
|
// case array/slice
|
||||||
var items *Items
|
var items *Schema
|
||||||
if golangType.Kind() == reflect.Array || golangType.Kind() == reflect.Slice {
|
if golangType.Kind() == reflect.Array || golangType.Kind() == reflect.Slice {
|
||||||
elemGolangType := golangType.Elem()
|
elemGolangType := golangType.Elem()
|
||||||
elemJavascriptType, err := javascriptType(elemGolangType)
|
elemJavascriptType, err := javascriptType(elemGolangType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
elemProps, err := safeToProperty(elemGolangType, seenTypes, debugTrace)
|
elemProps, err := safeToSchema(elemGolangType, seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
items = &Items{
|
items = &Schema{
|
||||||
// TODO: Add a test for slice of object
|
// TODO: Add a test for slice of object
|
||||||
Type: elemJavascriptType,
|
Type: elemJavascriptType,
|
||||||
Properties: elemProps.Properties,
|
Properties: elemProps.Properties,
|
||||||
|
@ -236,21 +224,21 @@ func toProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, de
|
||||||
}
|
}
|
||||||
|
|
||||||
// case map
|
// case map
|
||||||
var additionalProperties *Property
|
var additionalProperties *Schema
|
||||||
if golangType.Kind() == reflect.Map {
|
if golangType.Kind() == reflect.Map {
|
||||||
if golangType.Key().Kind() != reflect.String {
|
if golangType.Key().Kind() != reflect.String {
|
||||||
return nil, fmt.Errorf("only string keyed maps allowed")
|
return nil, fmt.Errorf("only string keyed maps allowed")
|
||||||
}
|
}
|
||||||
// TODO: Add a test for map of maps, and map of slices. Check that there
|
// TODO: Add a test for map of maps, and map of slices. Check that there
|
||||||
// is already a test for map of objects and map of primites
|
// is already a test for map of objects and map of primites
|
||||||
additionalProperties, err = safeToProperty(golangType.Elem(), seenTypes, debugTrace)
|
additionalProperties, err = safeToSchema(golangType.Elem(), seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// case struct
|
// case struct
|
||||||
properties := map[string]*Property{}
|
properties := map[string]*Schema{}
|
||||||
if golangType.Kind() == reflect.Struct {
|
if golangType.Kind() == reflect.Struct {
|
||||||
children := []reflect.StructField{}
|
children := []reflect.StructField{}
|
||||||
children = addStructFields(children, golangType)
|
children = addStructFields(children, golangType)
|
||||||
|
@ -268,7 +256,7 @@ func toProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, de
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursively compute properties for this child field
|
// recursively compute properties for this child field
|
||||||
fieldProps, err := safeToProperty(child.Type, seenTypes, debugTrace)
|
fieldProps, err := safeToSchema(child.Type, seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -280,7 +268,7 @@ func toProperty(golangType reflect.Type, seenTypes map[reflect.Type]struct{}, de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Property{
|
return &Schema{
|
||||||
Type: rootJavascriptType,
|
Type: rootJavascriptType,
|
||||||
Items: items,
|
Items: items,
|
||||||
Properties: properties,
|
Properties: properties,
|
||||||
|
|
Loading…
Reference in New Issue