Packages
oaspec
0.19.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.1
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.3
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.1.3
Generate Gleam code from OpenAPI 3.x specifications
Current section
Files
Jump to
Current section
Files
src/oaspec/codegen/allof_merge.gleam
import gleam/dict
import gleam/int
import gleam/list
import oaspec/codegen/context.{type Context}
import oaspec/openapi/resolver
import oaspec/openapi/schema.{
type AdditionalProperties, type SchemaRef, Forbidden, Inline, ObjectSchema,
Reference, Typed, Unspecified, Untyped,
}
/// Result of merging allOf sub-schemas.
pub type MergedAllOf {
MergedAllOf(
properties: dict.Dict(String, SchemaRef),
required: List(String),
additional_properties: AdditionalProperties,
)
}
/// Merge allOf sub-schemas: properties, required, and additionalProperties.
/// Non-object sub-schemas (primitives, arrays) are included as a synthetic
/// "value" property to preserve their constraints.
pub fn merge_allof_schemas(
schemas: List(SchemaRef),
ctx: Context,
) -> MergedAllOf {
list.index_fold(
schemas,
MergedAllOf(
properties: dict.new(),
required: [],
additional_properties: Unspecified,
),
fn(acc, s_ref, idx) {
let resolved = case s_ref {
Inline(obj) -> Ok(obj)
Reference(..) -> resolver.resolve_schema_ref(s_ref, context.spec(ctx))
}
case resolved {
Ok(ObjectSchema(properties:, required:, additional_properties:, ..)) -> {
let merged_ap = case
additional_properties,
acc.additional_properties
{
// Strongest declaration wins: Typed > Untyped > Forbidden >
// Unspecified. Forbidden beats Unspecified because explicit
// false is a real constraint while absent AP just means "no
// surface in generated types"; merging the two should keep
// the constraint.
Typed(x), _ -> Typed(x)
_, Typed(x) -> Typed(x)
Untyped, _ -> Untyped
_, Untyped -> Untyped
Forbidden, _ -> Forbidden
_, Forbidden -> Forbidden
Unspecified, Unspecified -> Unspecified
}
MergedAllOf(
properties: dict.merge(acc.properties, properties),
required: list.append(acc.required, required),
additional_properties: merged_ap,
)
}
// Non-object sub-schemas: add as a synthetic "value" field
Ok(schema_obj) -> {
let field_name = case idx {
0 -> "value"
n -> "value_" <> int.to_string(n)
}
MergedAllOf(
..acc,
properties: dict.insert(
acc.properties,
field_name,
Inline(schema_obj),
),
required: [field_name, ..acc.required],
)
}
_ -> acc
}
},
)
}