Skip to content

Commit

Permalink
Show path for schema errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sporto committed Nov 15, 2024
1 parent 25b2cdb commit 956a39f
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 8 deletions.
41 changes: 34 additions & 7 deletions src/oas.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ fn with_default(decoder, value) {
}
}

fn add_to_decode_error_path(
error: dynamic.DecodeError,
path: String,
) -> dynamic.DecodeError {
dynamic.DecodeError(..error, path: list.append(error.path, [path]))
}

/// This is the root object of the OpenAPI document.
pub type Document {
Document(
Expand Down Expand Up @@ -176,7 +183,7 @@ fn server_variable_decoder(raw) {
)(raw)
}

/// Describes the operations available on a single path.
/// Describes the operations available on a single path.
pub type PathItem {
PathItem(
summary: Option(String),
Expand Down Expand Up @@ -242,14 +249,11 @@ pub type Components {
)
}

fn components_decoder(raw) {
@internal
pub fn components_decoder(raw) {
dynamic.decode4(
Components,
default_field(
"schemas",
dynamic.dict(dynamic.string, schema_decoder),
dict.new(),
),
default_field("schemas", schemas_decoder, dict.new()),
default_field(
"responses",
dynamic.dict(dynamic.string, ref_decoder(response_decoder)),
Expand Down Expand Up @@ -475,6 +479,29 @@ pub type Schema {
OneOf(List(Ref(Schema)))
}

fn schemas_decoder(raw) {
dynamic.dict(dynamic.string, dynamic.dynamic)(raw)
|> result.then(fn(dict_with_dyn) {
dict.fold(
over: dict_with_dyn,
from: Ok(dict.new()),
with: fn(acc, key, value) {
case acc {
Error(errors) -> Error(errors)
Ok(dict) -> {
case schema_decoder(value) {
Ok(schema) -> Ok(dict.insert(dict, key, schema))
Error(errors) -> {
Error(list.map(errors, add_to_decode_error_path(_, key)))
}
}
}
}
},
)
})
}

fn schema_decoder(raw) {
dynamic.any([
dynamic.field("type", fn(field) {
Expand Down
54 changes: 53 additions & 1 deletion test/oas_test.gleam
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import gleam/dict
import gleam/dynamic
import gleam/json
import gleam/result
import gleeunit
Expand All @@ -13,6 +14,10 @@ fn parse(data) {
json.decode(data, oas.decoder)
}

fn decode_components(data) {
json.decode(data, oas.components_decoder)
}

pub fn minimal_doc_test() {
let doc =
"{\"openapi\": \"3.0.0\", \"info\": {\"title\": \"Test\", \"version\": \"0.x.x\" }}"
Expand All @@ -30,7 +35,7 @@ pub fn minimal_doc_test() {
pub fn minimal_doc_null_fields_test() {
let doc =
"{
\"openapi\": \"3.0.0\",
\"openapi\": \"3.0.0\",
\"info\": {\"title\": \"Test\", \"version\": \"0.x.x\" },
\"jsonSchemaDialect\": null,
\"servers\": null,
Expand Down Expand Up @@ -83,3 +88,50 @@ pub fn empty_paths_test() {
dict.get(paths, "/")
|> should.be_ok
}

pub fn valid_object_schema_test() {
let data =
"{
\"schemas\": {
\"thing\": {
\"type\": \"object\",
\"properties\": {
\"title\": {
\"type\": \"string\"
}
}
}
}
}"

data
|> decode_components
|> should.be_ok
}

pub fn invalid_object_schema_test() {
let data =
"{
\"schemas\": {
\"thing\": {
\"properties\": {
\"title\": {
\"type\": \"string\"
}
}
}
}
}"

data
|> decode_components
|> should.equal(
Error(
json.UnexpectedFormat([
dynamic.DecodeError(expected: "another type", found: "Object", path: [
"schemas", "thing",
]),
]),
),
)
}

0 comments on commit 956a39f

Please sign in to comment.