Skip to content

Commit

Permalink
fix: allow object and array without type name (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac authored Dec 28, 2024
1 parent 99e7c51 commit 1e0043f
Show file tree
Hide file tree
Showing 20 changed files with 1,762 additions and 679 deletions.
58 changes: 37 additions & 21 deletions ndc-http-schema/openapi/internal/oas2.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,14 @@ import (

// OAS2Builder the NDC schema builder from OpenAPI 2.0 specification
type OAS2Builder struct {
*ConvertOptions

schema *rest.NDCHttpSchema
// stores prebuilt and evaluating information of component schema types.
// some undefined schema types aren't stored in either object nor scalar,
// or self-reference types that haven't added into the object_types map yet.
// This cache temporarily stores them to avoid infinite recursive reference.
schemaCache map[string]SchemaInfoCache
*OASBuilderState
}

// NewOAS2Builder creates an OAS3Builder instance
func NewOAS2Builder(options ConvertOptions) *OAS2Builder {
builder := &OAS2Builder{
schema: rest.NewNDCHttpSchema(),
schemaCache: make(map[string]SchemaInfoCache),
ConvertOptions: applyConvertOptions(options),
return &OAS2Builder{
OASBuilderState: NewOASBuilderState(options),
}

return builder
}

func (oc *OAS2Builder) BuildDocumentModel(docModel *libopenapi.DocumentModel[v2.Swagger]) (*rest.NDCHttpSchema, error) {
Expand Down Expand Up @@ -208,7 +197,7 @@ func (oc *OAS2Builder) convertComponentSchemas(schemaItem orderedmap.Pair[string
return nil
}

schemaResult, err := newOAS2SchemaBuilder(oc, "", rest.InBody).getSchemaType(typeSchema, []string{typeKey})
schemaResult, err := newOASSchemaBuilder(oc.OASBuilderState, "", rest.InBody).getSchemaType(typeSchema, []string{typeKey})
if err != nil {
return err
}
Expand Down Expand Up @@ -257,12 +246,39 @@ func (oc *OAS2Builder) convertComponentSchemas(schemaItem orderedmap.Pair[string
return err
}

// build a named type for JSON scalar
func (oc *OAS2Builder) buildScalarJSON() *schema.NamedType {
scalarName := string(rest.ScalarJSON)
if _, ok := oc.schema.ScalarTypes[scalarName]; !ok {
oc.schema.ScalarTypes[scalarName] = *defaultScalarTypes[rest.ScalarJSON]
// get and convert an OpenAPI data type to a NDC type from parameter
func (oc *OAS2Builder) getSchemaTypeFromParameter(param *v2.Parameter, fieldPaths []string) (schema.TypeEncoder, error) {
var typeEncoder schema.TypeEncoder
nullable := param.Required == nil || !*param.Required

paramType := param.Type
hasArrayItem := param.Items != nil && param.Items.Type != ""
if param.Type == "" && hasArrayItem {
paramType = "array"
}

switch paramType {
case "object":
return nil, fmt.Errorf("%s: unsupported object parameter", strings.Join(fieldPaths, "."))
case "array":
if param.Items == nil || param.Items.Type == "" {
typeEncoder = schema.NewArrayType(schema.NewNamedType(string(rest.ScalarJSON)))
} else {
itemName := getScalarFromType(oc.schema, []string{param.Items.Type}, param.Format, param.Enum, fieldPaths)
typeEncoder = schema.NewArrayType(schema.NewNamedType(itemName))
}
default:
if !isPrimitiveScalar([]string{param.Type}) {
return nil, fmt.Errorf("%s: unsupported schema type %s", strings.Join(fieldPaths, "."), param.Type)
}

scalarName := getScalarFromType(oc.schema, []string{param.Type}, param.Format, param.Enum, fieldPaths)
typeEncoder = schema.NewNamedType(scalarName)
}

if nullable {
return schema.NewNullableType(typeEncoder), nil
}

return schema.NewNamedType(scalarName)
return typeEncoder, nil
}
17 changes: 7 additions & 10 deletions ndc-http-schema/openapi/internal/oas2_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (oc *oas2OperationBuilder) BuildFunction(operation *v2.Operation, commonPar
}

description := oc.getOperationDescription(operation)
requestURL, arguments, err := evalOperationPath(oc.builder.schema, oc.pathKey, oc.Arguments)
requestURL, arguments, err := evalOperationPath(oc.pathKey, oc.Arguments)
if err != nil {
return nil, "", fmt.Errorf("%s: %w", funcName, err)
}
Expand Down Expand Up @@ -142,7 +142,7 @@ func (oc *oas2OperationBuilder) BuildProcedure(operation *v2.Operation, commonPa
}

description := oc.getOperationDescription(operation)
requestURL, arguments, err := evalOperationPath(oc.builder.schema, oc.pathKey, arguments)
requestURL, arguments, err := evalOperationPath(oc.pathKey, arguments)
if err != nil {
return fmt.Errorf("%s: %w", procName, err)
}
Expand Down Expand Up @@ -204,8 +204,7 @@ func (oc *oas2OperationBuilder) convertParameters(operation *v2.Operation, commo

switch {
case param.Type != "":
typeEncoder, err := newOAS2SchemaBuilder(oc.builder, oc.pathKey, rest.ParameterLocation(param.In)).
getSchemaTypeFromParameter(param, fieldPaths)
typeEncoder, err := oc.builder.getSchemaTypeFromParameter(param, fieldPaths)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -235,13 +234,13 @@ func (oc *oas2OperationBuilder) convertParameters(operation *v2.Operation, commo
schemaResult.TypeSchema.MinLength = &minLength
}
case param.Schema != nil:
schemaResult, err = newOAS2SchemaBuilder(oc.builder, oc.pathKey, rest.ParameterLocation(param.In)).
schemaResult, err = newOASSchemaBuilder(oc.builder.OASBuilderState, oc.pathKey, rest.ParameterLocation(param.In)).
getSchemaTypeFromProxy(param.Schema, !paramRequired, fieldPaths)
if err != nil {
return nil, nil, err
}
default:
typeEncoder := oc.builder.buildScalarJSON()
typeEncoder := schema.NewNamedType(string(rest.ScalarJSON))
schemaResult = &SchemaInfoCache{
TypeRead: typeEncoder,
TypeWrite: typeEncoder,
Expand Down Expand Up @@ -382,24 +381,22 @@ func (oc *oas2OperationBuilder) convertResponse(operation *v2.Operation, fieldPa
if resp == nil || resp.Schema == nil {
if statusCode == http.StatusNoContent {
scalarName := rest.ScalarBoolean
oc.builder.schema.AddScalar(string(scalarName), *defaultScalarTypes[scalarName])

return schema.NewNullableNamedType(string(scalarName)), response, nil
}

if contentType != "" {
scalarName := guessScalarResultTypeFromContentType(contentType)
oc.builder.schema.AddScalar(string(scalarName), *defaultScalarTypes[scalarName])

return schema.NewNamedType(string(scalarName)), response, nil
}
}

if resp.Schema == nil {
return getResultTypeFromContentType(oc.builder.schema, contentType), response, nil
return getResultTypeFromContentType(contentType), response, nil
}

schemaResult, err := newOAS2SchemaBuilder(oc.builder, oc.pathKey, rest.InBody).
schemaResult, err := newOASSchemaBuilder(oc.builder.OASBuilderState, oc.pathKey, rest.InBody).
getSchemaTypeFromProxy(resp.Schema, false, fieldPaths)
if err != nil {
return nil, nil, err
Expand Down
Loading

0 comments on commit 1e0043f

Please sign in to comment.