-module(sqlode@codegen@common). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/sqlode/codegen/common.gleam"). -export([has_slices/1, queries_have_slices/1, render_enum_or_set_decoder/2, qualified_field_type/2, queries_have_enum_params/1, queries_have_enums/1, custom_type_imports/1, result_scalar_types/1, param_scalar_types/1, catalog_scalar_types/1, escape_string/1, out_to_module_path/1, runtime_import_path/1, gleam_type/2, gleam_fn/4]). -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/sqlode/codegen/common.gleam", 9). -spec has_slices(list(sqlode@model:query_param())) -> boolean(). has_slices(Params) -> gleam@list:any(Params, fun(P) -> erlang:element(6, P) end). -file("src/sqlode/codegen/common.gleam", 13). -spec queries_have_slices(list(sqlode@model:analyzed_query())) -> boolean(). queries_have_slices(Queries) -> gleam@list:any( Queries, fun(Query) -> has_slices(erlang:element(3, Query)) end ). -file("src/sqlode/codegen/common.gleam", 23). ?DOC( " Wrap the base decoder for `EnumType` and `SetType` columns so the\n" " decoded value reaches the consuming record as the generated sum\n" " type (or list of sum-type values for SET) rather than the raw\n" " wire string. `fallback` is the decoder to use for every other\n" " scalar type (adapter-specific in the caller — e.g. pog's\n" " `decode.bool` vs sqlight's int-to-bool adapter).\n" ). -spec render_enum_or_set_decoder( sqlode@model:scalar_type(), fun((sqlode@model:scalar_type()) -> binary()) ) -> binary(). render_enum_or_set_decoder(Scalar_type, Fallback) -> case Scalar_type of {enum_type, Enum_name} -> <<<<<<<<<<<<"decode.then(decode.string, fn(s) { case models."/utf8, (sqlode@type_mapping:enum_from_string_fn( Enum_name ))/binary>>/binary, "(s) { Ok(v) -> decode.success(v) Error(_) -> decode.failure(models."/utf8>>/binary, (sqlode@type_mapping:enum_default_fn(Enum_name))/binary>>/binary, "(), \"valid "/utf8>>/binary, Enum_name/binary>>/binary, " value\") } })"/utf8>>; {set_type, Set_name} -> <<<<<<<<"decode.then(decode.string, fn(s) { case models."/utf8, (sqlode@type_mapping:set_from_string_fn(Set_name))/binary>>/binary, "(s) { Ok(v) -> decode.success(v) Error(_) -> decode.failure([], \"valid "/utf8>>/binary, Set_name/binary>>/binary, " set\") } })"/utf8>>; _ -> Fallback(Scalar_type) end. -file("src/sqlode/codegen/common.gleam", 58). ?DOC( " Render a param / record field's Gleam type for generated modules\n" " that are NOT `models.gleam` itself (currently `params.gleam` and\n" " `queries.gleam`). They reach the generated `EnumType` / `SetType`\n" " definitions through a plain `import db/models`, so every external\n" " reference must be qualified with `models.` — the bare names only\n" " work inside `models.gleam` where the types are declared.\n" " `ArrayType` recurses so arrays of enum / set stay qualified.\n" ). -spec qualified_field_type( sqlode@model:scalar_type(), sqlode@model:type_mapping() ) -> binary(). qualified_field_type(Scalar_type, Type_mapping_mode) -> case Scalar_type of {enum_type, _} -> <<"models."/utf8, (sqlode@type_mapping:scalar_type_to_gleam_type( Scalar_type, Type_mapping_mode ))/binary>>; {set_type, Name} -> <<<<"List(models."/utf8, (sqlode@type_mapping:set_value_type_name(Name))/binary>>/binary, ")"/utf8>>; {array_type, Element} -> <<<<"List("/utf8, (qualified_field_type(Element, Type_mapping_mode))/binary>>/binary, ")"/utf8>>; _ -> sqlode@type_mapping:scalar_type_to_gleam_type( Scalar_type, Type_mapping_mode ) end. -file("src/sqlode/codegen/common.gleam", 74). -spec queries_have_enum_params(list(sqlode@model:analyzed_query())) -> boolean(). queries_have_enum_params(Queries) -> gleam@list:any( Queries, fun(Query) -> gleam@list:any( erlang:element(3, Query), fun(Param) -> case erlang:element(4, Param) of {enum_type, _} -> true; {set_type, _} -> true; _ -> false end end ) end ). -file("src/sqlode/codegen/common.gleam", 85). -spec queries_have_enums(list(sqlode@model:analyzed_query())) -> boolean(). queries_have_enums(Queries) -> gleam@list:any( Queries, fun(Query) -> gleam@list:any( erlang:element(3, Query), fun(Param) -> case erlang:element(4, Param) of {enum_type, _} -> true; {set_type, _} -> true; _ -> false end end ) orelse gleam@list:any( erlang:element(4, Query), fun(Col) -> case Col of {scalar_result, {result_column, _, {enum_type, _}, _, _}} -> true; {scalar_result, {result_column, _, {set_type, _}, _, _}} -> true; _ -> false end end ) end ). -file("src/sqlode/codegen/common.gleam", 110). ?DOC(" Collect import statements for module-qualified custom types from scalar types.\n"). -spec custom_type_imports(list(sqlode@model:scalar_type())) -> list(binary()). custom_type_imports(Scalar_types) -> _pipe = Scalar_types, _pipe@1 = gleam@list:filter_map(_pipe, fun(St) -> case St of {custom_type, Name, {some, Module}, _} -> {ok, <<<<<<<<"import "/utf8, Module/binary>>/binary, ".{type "/utf8>>/binary, Name/binary>>/binary, "}"/utf8>>}; _ -> {error, nil} end end), _pipe@2 = gleam@list:unique(_pipe@1), gleam@list:sort(_pipe@2, fun gleam@string:compare/2). -file("src/sqlode/codegen/common.gleam", 124). ?DOC(" Collect all scalar types from query result columns.\n"). -spec result_scalar_types(list(sqlode@model:analyzed_query())) -> list(sqlode@model:scalar_type()). result_scalar_types(Queries) -> gleam@list:flat_map( Queries, fun(Query) -> gleam@list:filter_map( erlang:element(4, Query), fun(Col) -> case Col of {scalar_result, {result_column, _, Scalar_type, _, _}} -> {ok, Scalar_type}; {embedded_result, {embedded_column, _, _, Columns}} -> case gleam@list:find_map( Columns, fun(C) -> case erlang:element(3, C) of {custom_type, _, _, _} -> {ok, erlang:element(3, C)}; _ -> {error, nil} end end ) of {ok, St} -> {ok, St}; {error, _} -> {error, nil} end end end ) end ). -file("src/sqlode/codegen/common.gleam", 150). ?DOC(" Collect all scalar types from query params.\n"). -spec param_scalar_types(list(sqlode@model:analyzed_query())) -> list(sqlode@model:scalar_type()). param_scalar_types(Queries) -> gleam@list:flat_map( Queries, fun(Query) -> gleam@list:map( erlang:element(3, Query), fun(P) -> erlang:element(4, P) end ) end ). -file("src/sqlode/codegen/common.gleam", 159). ?DOC(" Collect all scalar types from catalog tables.\n"). -spec catalog_scalar_types(sqlode@model:catalog()) -> list(sqlode@model:scalar_type()). catalog_scalar_types(Catalog) -> gleam@list:flat_map( erlang:element(2, Catalog), fun(Table) -> gleam@list:map( erlang:element(3, Table), fun(Col) -> erlang:element(3, Col) end ) end ). -file("src/sqlode/codegen/common.gleam", 165). -spec escape_string(binary()) -> binary(). escape_string(Input) -> _pipe = Input, _pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>), _pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>), _pipe@3 = gleam@string:replace(_pipe@2, <<"\n"/utf8>>, <<"\\n"/utf8>>), _pipe@4 = gleam@string:replace(_pipe@3, <<"\r"/utf8>>, <<"\\r"/utf8>>), gleam@string:replace(_pipe@4, <<"\t"/utf8>>, <<"\\t"/utf8>>). -file("src/sqlode/codegen/common.gleam", 177). ?DOC( " Derive the Gleam module path from the output directory.\n" " Strips the \"src/\" prefix so imports match the actual file location.\n" " e.g. \"src/db\" -> \"db\", \"/abs/path/src/db\" -> \"db\"\n" ). -spec out_to_module_path(binary()) -> binary(). out_to_module_path(Out) -> case gleam_stdlib:string_starts_with(Out, <<"src/"/utf8>>) of true -> gleam@string:drop_start(Out, 4); false -> _pipe = gleam@string:split(Out, <<"/src/"/utf8>>), _pipe@1 = gleam@list:last(_pipe), gleam@result:unwrap(_pipe@1, Out) end. -file("src/sqlode/codegen/common.gleam", 192). ?DOC( " Import path used by generated modules for the sqlode runtime. When\n" " `gleam.vendor_runtime` is enabled, the runtime source is written\n" " into `/runtime.gleam` and the generated code points at that\n" " local copy (e.g. `db/runtime`). Otherwise the shared\n" " `sqlode/runtime` dependency is used.\n" ). -spec runtime_import_path(sqlode@model:gleam_output()) -> binary(). runtime_import_path(Gleam) -> case erlang:element(8, Gleam) of true -> <<(out_to_module_path(erlang:element(2, Gleam)))/binary, "/runtime"/utf8>>; false -> <<"sqlode/runtime"/utf8>> end. -file("src/sqlode/codegen/common.gleam", 205). ?DOC( " Render a single-constructor Gleam type declaration.\n" "\n" " gleam_type(\"UserId\", \"Int\") →\n" " \"pub type UserId {\n" " UserId(Int)\n" " }\"\n" ). -spec gleam_type(binary(), binary()) -> binary(). gleam_type(Name, Body) -> _pipe = sqlode@codegen@builder:concat( [sqlode@codegen@builder:line( <<<<"pub type "/utf8, Name/binary>>/binary, " {"/utf8>> ), sqlode@codegen@builder:line( <<<<<<<<" "/utf8, Name/binary>>/binary, "("/utf8>>/binary, Body/binary>>/binary, ")"/utf8>> ), sqlode@codegen@builder:line(<<"}"/utf8>>)] ), sqlode@codegen@builder:render(_pipe). -file("src/sqlode/codegen/common.gleam", 220). ?DOC( " Render a Gleam function declaration as a single string.\n" "\n" " gleam_fn(\"double\", \"x: Int\", \"Int\", \"x * 2\") →\n" " \"pub fn double(x: Int) -> Int {\n" " x * 2\n" " }\"\n" ). -spec gleam_fn(binary(), binary(), binary(), binary()) -> binary(). gleam_fn(Name, Params, Return_type, Body) -> _pipe = sqlode@codegen@builder:concat( [sqlode@codegen@builder:line( <<<<<<<<<<<<"pub fn "/utf8, Name/binary>>/binary, "("/utf8>>/binary, Params/binary>>/binary, ") -> "/utf8>>/binary, Return_type/binary>>/binary, " {"/utf8>> ), sqlode@codegen@builder:line(<<" "/utf8, Body/binary>>), sqlode@codegen@builder:line(<<"}"/utf8>>)] ), sqlode@codegen@builder:render(_pipe).