Skip to content

Commit

Permalink
fix: ensure parsing schema metadata isn't ambiguous
Browse files Browse the repository at this point in the history
An example of the ambiguity is on fields. Given an alias:

```
data Data {
  field Field alias json "foo"
}
```

This effectively prevents the next field from being named "alias":

```
data Data {
  field Field
  alias json "foo"
}
```

Metadata is now disambiguated by requiring a `+` before every piece of
metadata:

```
data Data {
  field Field +alias json "foo"
}
```

(also converted field aliases to metadata)
  • Loading branch information
alecthomas committed Mar 6, 2024
1 parent ac87ced commit 7a0f4a6
Show file tree
Hide file tree
Showing 30 changed files with 904 additions and 522 deletions.
14 changes: 8 additions & 6 deletions backend/controller/ingress/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,22 @@ func transformAliasedFields(sch *schema.Schema, t schema.Type, obj any, aliaser

func transformFromAliasedFields(dataRef *schema.DataRef, sch *schema.Schema, request map[string]any) (map[string]any, error) {
return request, transformAliasedFields(sch, dataRef, request, func(obj map[string]any, field *schema.Field) string {
if _, ok := obj[field.Name]; !ok && field.JSONAlias != "" && obj[field.JSONAlias] != nil {
obj[field.Name] = obj[field.JSONAlias]
delete(obj, field.JSONAlias)
jsonAlias := field.Alias(schema.AliasKindJSON)
if _, ok := obj[field.Name]; !ok && jsonAlias != "" && obj[jsonAlias] != nil {
obj[field.Name] = obj[jsonAlias]
delete(obj, jsonAlias)
}
return field.Name
})
}

func transformToAliasedFields(dataRef *schema.DataRef, sch *schema.Schema, request map[string]any) (map[string]any, error) {
return request, transformAliasedFields(sch, dataRef, request, func(obj map[string]any, field *schema.Field) string {
if field.JSONAlias != "" && field.Name != field.JSONAlias {
obj[field.JSONAlias] = obj[field.Name]
jsonAlias := field.Alias(schema.AliasKindJSON)
if jsonAlias != "" && field.Name != jsonAlias {
obj[jsonAlias] = obj[field.Name]
delete(obj, field.Name)
return field.JSONAlias
return jsonAlias
}
return field.Name
})
Expand Down
8 changes: 4 additions & 4 deletions backend/controller/ingress/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ func TestTransformFromAliasedFields(t *testing.T) {
schemaText := `
module test {
data Inner {
waz String alias json "foo"
waz String +alias json "foo"
}
data Test {
scalar String alias json "bar"
scalar String +alias json "bar"
inner Inner
array [Inner]
map {String: Inner}
Expand Down Expand Up @@ -72,11 +72,11 @@ func TestTransformToAliasedFields(t *testing.T) {
schemaText := `
module test {
data Inner {
waz String alias json "foo"
waz String +alias json "foo"
}
data Test {
scalar String alias json "bar"
scalar String +alias json "bar"
inner Inner
array [Inner]
map {String: Inner}
Expand Down
10 changes: 5 additions & 5 deletions backend/controller/ingress/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestIngress(t *testing.T) {
sch, err := schema.ParseString("", `
module test {
data AliasRequest {
aliased String alias json "alias"
aliased String +alias json "alias"
}
data PathParameterRequest {
Expand All @@ -43,16 +43,16 @@ func TestIngress(t *testing.T) {
}
verb getAlias(HttpRequest<AliasRequest>) HttpResponse<Empty, Empty>
ingress http GET /getAlias
+ingress http GET /getAlias
verb getPath(HttpRequest<PathParameterRequest>) HttpResponse<Empty, Empty>
ingress http GET /getPath/{username}
+ingress http GET /getPath/{username}
verb postMissingTypes(HttpRequest<MissingTypes>) HttpResponse<Empty, Empty>
ingress http POST /postMissingTypes
+ingress http POST /postMissingTypes
verb postJsonPayload(HttpRequest<JsonPayload>) HttpResponse<Empty, Empty>
ingress http POST /postJsonPayload
+ingress http POST /postJsonPayload
}
`)
assert.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion backend/controller/ingress/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func TestResponseBodyForVerb(t *testing.T) {
&schema.Data{
Name: "Test",
Fields: []*schema.Field{
{Name: "message", Type: &schema.String{}, JSONAlias: "msg"},
{Name: "message", Type: &schema.String{}, Metadata: []schema.Metadata{&schema.MetadataAlias{Kind: schema.AliasKindJSON, Alias: "msg"}}},
},
},
jsonVerb,
Expand Down
3 changes: 2 additions & 1 deletion backend/controller/ingress/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ func parseQueryParams(values url.Values, data *schema.Data) (map[string]any, err

var field *schema.Field
for _, f := range data.Fields {
if (f.JSONAlias != "" && f.JSONAlias == key) || f.Name == key {
jsonAlias := f.Alias(schema.AliasKindJSON)
if (jsonAlias != "" && jsonAlias == key) || f.Name == key {
field = f
}
for _, typeParam := range data.TypeParameters {
Expand Down
10 changes: 5 additions & 5 deletions backend/controller/ingress/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestBuildRequestBody(t *testing.T) {
sch, err := schema.ParseString("test", `
module test {
data AliasRequest {
aliased String alias json "alias"
aliased String +alias json "alias"
}
data PathParameterRequest {
Expand All @@ -69,16 +69,16 @@ func TestBuildRequestBody(t *testing.T) {
}
verb getAlias(HttpRequest<AliasRequest>) HttpResponse<Empty, Empty>
ingress http GET /getAlias
+ingress http GET /getAlias
verb getPath(HttpRequest<PathParameterRequest>) HttpResponse<Empty, Empty>
ingress http GET /getPath/{username}
+ingress http GET /getPath/{username}
verb postMissingTypes(HttpRequest<MissingTypes>) HttpResponse<Empty, Empty>
ingress http POST /postMissingTypes
+ingress http POST /postMissingTypes
verb postJsonPayload(HttpRequest<JsonPayload>) HttpResponse<Empty, Empty>
ingress http POST /postJsonPayload
+ingress http POST /postJsonPayload
}
`)
assert.NoError(t, err)
Expand Down
7 changes: 4 additions & 3 deletions backend/controller/ingress/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ func bodyForType(typ schema.Type, sch *schema.Schema, data []byte) ([]byte, erro
}

err = transformAliasedFields(sch, t, response, func(obj map[string]any, field *schema.Field) string {
if field.JSONAlias != "" && field.Name != field.JSONAlias {
obj[field.JSONAlias] = obj[field.Name]
jsonAlias := field.Alias(schema.AliasKindJSON)
if jsonAlias != "" && field.Name != jsonAlias {
obj[jsonAlias] = obj[field.Name]
delete(obj, field.Name)
return field.JSONAlias
return jsonAlias
}
return field.Name
})
Expand Down
Loading

0 comments on commit 7a0f4a6

Please sign in to comment.