-module(oaspec@codegen@schema_utils). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/codegen/schema_utils.gleam"). -export([schema_has_additional_properties/2, schema_has_untyped_additional_properties/2, constant_property_value/3, schema_ref_is_nullable/2, schema_has_optional_fields/2, schema_ref_is_read_only/2, schema_ref_is_write_only/2, filter_read_only_properties/2, filter_write_only_properties/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -file("src/oaspec/codegen/schema_utils.gleam", 15). ?DOC(" Check if a schema has typed or untyped additionalProperties that would need Dict.\n"). -spec schema_has_additional_properties( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_has_additional_properties(Schema_ref, Ctx) -> case Schema_ref of {inline, {object_schema, _, _, _, {typed, _}, _, _}} -> true; {inline, {object_schema, _, _, _, untyped, _, _}} -> true; {inline, {all_of_schema, _, Schemas}} -> gleam@list:any( Schemas, fun(S) -> schema_has_additional_properties(S, Ctx) end ); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Schema_ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Schema_obj} -> schema_has_additional_properties({inline, Schema_obj}, Ctx); {error, _} -> false end; _ -> false end. -file("src/oaspec/codegen/schema_utils.gleam", 36). ?DOC(" Check if a schema has untyped additionalProperties (needs Dynamic import).\n"). -spec schema_has_untyped_additional_properties( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_has_untyped_additional_properties(Schema_ref, Ctx) -> case Schema_ref of {inline, {object_schema, _, _, _, untyped, _, _}} -> true; {inline, {all_of_schema, _, Schemas}} -> gleam@list:any( Schemas, fun(S) -> schema_has_untyped_additional_properties(S, Ctx) end ); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Schema_ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Schema_obj} -> schema_has_untyped_additional_properties( {inline, Schema_obj}, Ctx ); {error, _} -> false end; _ -> false end. -file("src/oaspec/codegen/schema_utils.gleam", 92). ?DOC( " Issue #309: detect a property that is fully determined by the\n" " schema — an inline string-enum with exactly one allowed value that\n" " the parent schema lists as required. Such a property is a constant\n" " marker on the wire (e.g. a `kind: type: string, enum: [text]`\n" " discriminator on a oneOf variant): the only legal value is known\n" " at codegen time, so the generated record drops the field, the\n" " encoder emits the constant, and the decoder validates it.\n" "\n" " Returns `Some(value)` for an elidable constant property; `None`\n" " otherwise (including `$ref`s, multi-value enums, optional\n" " properties, and non-string schemas — those keep their current\n" " record-field shape).\n" ). -spec constant_property_value( oaspec@openapi@schema:schema_ref(), binary(), list(binary()) ) -> gleam@option:option(binary()). constant_property_value(Prop_ref, Prop_name, Required) -> case {gleam@list:contains(Required, Prop_name), Prop_ref} of {true, {inline, {string_schema, _, _, [Single_value], _, _, _}}} -> {some, Single_value}; {_, _} -> none end. -file("src/oaspec/codegen/schema_utils.gleam", 105). ?DOC(" Check if a SchemaRef is nullable, resolving $ref if needed.\n"). -spec schema_ref_is_nullable( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_ref_is_nullable(Ref, Ctx) -> case Ref of {inline, Inline_schema} -> oaspec@openapi@schema:is_nullable(Inline_schema); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Resolved} -> oaspec@openapi@schema:is_nullable(Resolved); {error, _} -> false end end. -file("src/oaspec/codegen/schema_utils.gleam", 58). ?DOC(" Check if a schema has any optional or nullable fields that would need Option.\n"). -spec schema_has_optional_fields( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_has_optional_fields(Schema_ref, Ctx) -> case Schema_ref of {inline, {object_schema, _, Properties, Required, _, _, _}} -> _pipe = maps:to_list(Properties), gleam@list:any( _pipe, fun(Entry) -> {Prop_name, Prop_ref} = Entry, not gleam@list:contains(Required, Prop_name) orelse schema_ref_is_nullable( Prop_ref, Ctx ) end ); {inline, {all_of_schema, _, Schemas}} -> gleam@list:any( Schemas, fun(S) -> schema_has_optional_fields(S, Ctx) end ); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Schema_ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Schema_obj} -> schema_has_optional_fields({inline, Schema_obj}, Ctx); {error, _} -> false end; _ -> false end. -file("src/oaspec/codegen/schema_utils.gleam", 118). ?DOC(" Check if a SchemaRef has readOnly metadata, resolving $ref if needed.\n"). -spec schema_ref_is_read_only( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_ref_is_read_only(Ref, Ctx) -> case Ref of {inline, Inline_schema} -> erlang:element(6, oaspec@openapi@schema:get_metadata(Inline_schema)); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Resolved} -> erlang:element( 6, oaspec@openapi@schema:get_metadata(Resolved) ); {error, _} -> false end end. -file("src/oaspec/codegen/schema_utils.gleam", 131). ?DOC(" Check if a SchemaRef has writeOnly metadata, resolving $ref if needed.\n"). -spec schema_ref_is_write_only( oaspec@openapi@schema:schema_ref(), oaspec@codegen@context:context() ) -> boolean(). schema_ref_is_write_only(Ref, Ctx) -> case Ref of {inline, Inline_schema} -> erlang:element(7, oaspec@openapi@schema:get_metadata(Inline_schema)); {reference, _, _} -> case oaspec@openapi@resolver:resolve_schema_ref( Ref, oaspec@codegen@context:spec(Ctx) ) of {ok, Resolved} -> erlang:element( 7, oaspec@openapi@schema:get_metadata(Resolved) ); {error, _} -> false end end. -file("src/oaspec/codegen/schema_utils.gleam", 145). ?DOC( " Filter readOnly properties from an ObjectSchema for request body context.\n" " Returns a new schema with readOnly properties removed.\n" ). -spec filter_read_only_properties( oaspec@openapi@schema:schema_object(), oaspec@codegen@context:context() ) -> oaspec@openapi@schema:schema_object(). filter_read_only_properties(Schema_obj, Ctx) -> case Schema_obj of {object_schema, Metadata, Properties, Required, Additional_properties, Min_properties, Max_properties} -> Filtered_props = gleam@dict:filter( Properties, fun(_, Prop_ref) -> not schema_ref_is_read_only(Prop_ref, Ctx) end ), Filtered_required = gleam@list:filter( Required, fun(Name) -> case gleam_stdlib:map_get(Filtered_props, Name) of {ok, _} -> true; {error, _} -> false end end ), {object_schema, Metadata, Filtered_props, Filtered_required, Additional_properties, Min_properties, Max_properties}; _ -> Schema_obj end. -file("src/oaspec/codegen/schema_utils.gleam", 185). ?DOC( " Filter writeOnly properties from an ObjectSchema for response body context.\n" " Returns a new schema with writeOnly properties removed.\n" ). -spec filter_write_only_properties( oaspec@openapi@schema:schema_object(), oaspec@codegen@context:context() ) -> oaspec@openapi@schema:schema_object(). filter_write_only_properties(Schema_obj, Ctx) -> case Schema_obj of {object_schema, Metadata, Properties, Required, Additional_properties, Min_properties, Max_properties} -> Filtered_props = gleam@dict:filter( Properties, fun(_, Prop_ref) -> not schema_ref_is_write_only(Prop_ref, Ctx) end ), Filtered_required = gleam@list:filter( Required, fun(Name) -> case gleam_stdlib:map_get(Filtered_props, Name) of {ok, _} -> true; {error, _} -> false end end ), {object_schema, Metadata, Filtered_props, Filtered_required, Additional_properties, Min_properties, Max_properties}; _ -> Schema_obj end.