-module(cquill@dev). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/cquill/dev.gleam"). -export([default_config/0, minimal_config/0, verbose_config/0, is_enabled/0, get_config/0, log_pool_stats/1, update_pool_stats/1, pool_stats/7, enable_with_config/1, enable/0, enable_from_env/0, disable/0, configure/1, stop/0]). -export_type([dev_config/0, dev_message/0, dev_state/0, pool_stats/0, dev_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type dev_config() :: {dev_config, boolean(), boolean(), boolean(), integer(), boolean(), integer(), list(binary()), binary(), boolean()}. -type dev_message() :: {enable, dev_config(), gleam@erlang@process:subject({ok, nil} | {error, dev_error()})} | {disable, gleam@erlang@process:subject({ok, nil} | {error, dev_error()})} | {get_config, gleam@erlang@process:subject(gleam@option:option(dev_config()))} | {is_enabled, gleam@erlang@process:subject(boolean())} | {update_config, dev_config(), gleam@erlang@process:subject({ok, nil} | {error, dev_error()})} | {update_pool_stats, pool_stats()}. -type dev_state() :: {dev_state, gleam@option:option(dev_config()), gleam@option:option(pool_stats())}. -type pool_stats() :: {pool_stats, binary(), integer(), integer(), integer(), integer(), integer(), integer()}. -type dev_error() :: already_enabled | not_enabled | telemetry_required | dev_mode_not_running. -file("src/cquill/dev.gleam", 65). ?DOC(" Create a default configuration\n"). -spec default_config() -> dev_config(). default_config() -> {dev_config, true, true, true, 100, false, 10000, [<<"password"/utf8>>, <<"token"/utf8>>, <<"secret"/utf8>>, <<"key"/utf8>>, <<"credential"/utf8>>, <<"api_key"/utf8>>], <<"[REDACTED]"/utf8>>, false}. -file("src/cquill/dev.gleam", 80). ?DOC(" Create a minimal configuration (queries only, no params)\n"). -spec minimal_config() -> dev_config(). minimal_config() -> {dev_config, true, true, false, 500, false, 30000, [], <<"[REDACTED]"/utf8>>, false}. -file("src/cquill/dev.gleam", 95). ?DOC(" Create a verbose configuration (all debugging enabled)\n"). -spec verbose_config() -> dev_config(). verbose_config() -> {dev_config, true, true, true, 50, true, 5000, [<<"password"/utf8>>, <<"token"/utf8>>, <<"secret"/utf8>>, <<"key"/utf8>>, <<"credential"/utf8>>, <<"api_key"/utf8>>], <<"[REDACTED]"/utf8>>, true}. -file("src/cquill/dev.gleam", 178). ?DOC(" Start the dev mode server\n"). -spec start_server() -> {ok, gleam@erlang@process:subject(dev_message())} | {error, gleam@otp@actor:start_error()}. start_server() -> Initial_state = {dev_state, none, none}, _pipe = gleam@otp@actor:new(Initial_state), _pipe@1 = gleam@otp@actor:on_message(_pipe, fun(State, Msg) -> case Msg of {enable, Config, Reply_to} -> case erlang:element(2, State) of {some, _} -> gleam@erlang@process:send( Reply_to, {error, already_enabled} ), gleam@otp@actor:continue(State); none -> gleam@erlang@process:send(Reply_to, {ok, nil}), gleam@otp@actor:continue( {dev_state, {some, Config}, erlang:element(3, State)} ) end; {disable, Reply_to@1} -> case erlang:element(2, State) of {some, _} -> gleam@erlang@process:send(Reply_to@1, {ok, nil}), gleam@otp@actor:continue({dev_state, none, none}); none -> gleam@erlang@process:send( Reply_to@1, {error, not_enabled} ), gleam@otp@actor:continue(State) end; {get_config, Reply_to@2} -> gleam@erlang@process:send( Reply_to@2, erlang:element(2, State) ), gleam@otp@actor:continue(State); {is_enabled, Reply_to@3} -> gleam@erlang@process:send( Reply_to@3, gleam@option:is_some(erlang:element(2, State)) ), gleam@otp@actor:continue(State); {update_config, Config@1, Reply_to@4} -> case erlang:element(2, State) of {some, _} -> gleam@erlang@process:send(Reply_to@4, {ok, nil}), gleam@otp@actor:continue( {dev_state, {some, Config@1}, erlang:element(3, State)} ); none -> gleam@erlang@process:send( Reply_to@4, {error, not_enabled} ), gleam@otp@actor:continue(State) end; {update_pool_stats, Stats} -> gleam@otp@actor:continue( {dev_state, erlang:element(2, State), {some, Stats}} ) end end), _pipe@2 = gleam@otp@actor:start(_pipe@1), gleam@result:map(_pipe@2, fun(Started) -> erlang:element(3, Started) end). -file("src/cquill/dev.gleam", 312). ?DOC(" Check if development mode is enabled\n"). -spec is_enabled() -> boolean(). is_enabled() -> case cquill_dev_ffi:get_dev_server() of {error, _} -> false; {ok, Server} -> gleam@erlang@process:call( Server, 5000, fun(Reply_to) -> {is_enabled, Reply_to} end ) end. -file("src/cquill/dev.gleam", 322). ?DOC(" Get the current configuration (if enabled)\n"). -spec get_config() -> gleam@option:option(dev_config()). get_config() -> case cquill_dev_ffi:get_dev_server() of {error, _} -> none; {ok, Server} -> gleam@erlang@process:call( Server, 5000, fun(Reply_to) -> {get_config, Reply_to} end ) end. -file("src/cquill/dev.gleam", 568). ?DOC(" Pool events handler\n"). -spec dev_pool_handler() -> fun((cquill@telemetry:event(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> nil). dev_pool_handler() -> fun(Event, _) -> case Event of {pool_checkout, E} -> Wait_ms = erlang:element(3, E) div 1000, case Wait_ms > 10 of true -> gleam_stdlib:println( erlang:list_to_binary( [<<"[cquill] Pool checkout: "/utf8>>, erlang:element(2, E), <<" (waited "/utf8>>, erlang:integer_to_binary(Wait_ms), <<"ms, queue: "/utf8>>, erlang:integer_to_binary( erlang:element(4, E) ), <<")"/utf8>>] ) ); false -> nil end; {pool_timeout, E@1} -> Wait_ms@1 = erlang:element(3, E@1) div 1000, gleam_stdlib:println_error( erlang:list_to_binary( [<<"[cquill] \x{26A0}\x{FE0F} Pool TIMEOUT: "/utf8>>, erlang:element(2, E@1), <<" after "/utf8>>, erlang:integer_to_binary(Wait_ms@1), <<"ms (queue: "/utf8>>, erlang:integer_to_binary(erlang:element(4, E@1)), <<")"/utf8>>] ) ), gleam_stdlib:println_error( <<" Hint: Consider increasing pool size"/utf8>> ); _ -> nil end end. -file("src/cquill/dev.gleam", 612). ?DOC(" Transaction events handler\n"). -spec dev_transaction_handler() -> fun((cquill@telemetry:event(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> nil). dev_transaction_handler() -> fun(Event, _) -> case Event of {transaction_start, E} -> gleam_stdlib:println( <<"[cquill] Transaction started: "/utf8, (erlang:element(2, E))/binary>> ); {transaction_commit, E@1} -> Duration_ms = erlang:element(3, E@1) div 1000, gleam_stdlib:println( erlang:list_to_binary( [<<"[cquill] Transaction committed: "/utf8>>, erlang:element(2, E@1), <<" ["/utf8>>, erlang:integer_to_binary(Duration_ms), <<"ms, "/utf8>>, erlang:integer_to_binary(erlang:element(4, E@1)), <<" queries]"/utf8>>] ) ); {transaction_rollback, E@2} -> Duration_ms@1 = erlang:element(3, E@2) div 1000, Reason_str = case erlang:element(4, E@2) of {some, R} -> <<" - "/utf8, R/binary>>; none -> <<""/utf8>> end, gleam_stdlib:println_error( erlang:list_to_binary( [<<"[cquill] Transaction rolled back: "/utf8>>, erlang:element(2, E@2), Reason_str, <<" ["/utf8>>, erlang:integer_to_binary(Duration_ms@1), <<"ms]"/utf8>>] ) ); _ -> nil end end. -file("src/cquill/dev.gleam", 662). ?DOC(" Log current pool statistics\n"). -spec log_pool_stats(pool_stats()) -> nil. log_pool_stats(Stats) -> gleam_stdlib:println(<<"[cquill] Pool stats:"/utf8>>), gleam_stdlib:println( <<" - Name: "/utf8, (erlang:element(2, Stats))/binary>> ), gleam_stdlib:println( <<" - Size: "/utf8, (erlang:integer_to_binary(erlang:element(3, Stats)))/binary>> ), gleam_stdlib:println( <<" - In use: "/utf8, (erlang:integer_to_binary(erlang:element(4, Stats)))/binary>> ), gleam_stdlib:println( <<" - Available: "/utf8, (erlang:integer_to_binary(erlang:element(5, Stats)))/binary>> ), gleam_stdlib:println( <<" - Waiting: "/utf8, (erlang:integer_to_binary(erlang:element(6, Stats)))/binary>> ), gleam_stdlib:println( <<" - Checkouts: "/utf8, (erlang:integer_to_binary(erlang:element(7, Stats)))/binary>> ), gleam_stdlib:println( <<" - Timeouts: "/utf8, (erlang:integer_to_binary(erlang:element(8, Stats)))/binary>> ). -file("src/cquill/dev.gleam", 674). ?DOC(" Update pool statistics in dev mode server\n"). -spec update_pool_stats(pool_stats()) -> nil. update_pool_stats(Stats) -> case cquill_dev_ffi:get_dev_server() of {error, _} -> nil; {ok, Server} -> gleam@erlang@process:send(Server, {update_pool_stats, Stats}) end. -file("src/cquill/dev.gleam", 684). ?DOC(" Create pool stats from values\n"). -spec pool_stats( binary(), integer(), integer(), integer(), integer(), integer(), integer() ) -> pool_stats(). pool_stats( Pool_name, Size, In_use, Available, Waiting, Total_checkouts, Total_timeouts ) -> {pool_stats, Pool_name, Size, In_use, Available, Waiting, Total_checkouts, Total_timeouts}. -file("src/cquill/dev.gleam", 753). ?DOC(" Check if a value should be masked based on heuristics\n"). -spec should_mask_value(binary(), list(binary())) -> boolean(). should_mask_value(Value, _) -> Is_long_string = string:length(Value) > 32, Looks_like_hash = gleam_stdlib:contains_string(Value, <<"$2"/utf8>>) orelse gleam_stdlib:contains_string( Value, <<"sha"/utf8>> ), Looks_like_token = (gleam_stdlib:contains_string(Value, <<"bearer"/utf8>>) orelse gleam_stdlib:contains_string(Value, <<"token"/utf8>>)) orelse gleam_stdlib:contains_string(Value, <<"api_key"/utf8>>), Is_long_string andalso (Looks_like_hash orelse Looks_like_token). -file("src/cquill/dev.gleam", 767). ?DOC(" Escape special characters in a string for display\n"). -spec escape_string(binary()) -> binary(). escape_string(S) -> _pipe = S, _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>>), gleam@string:replace(_pipe@3, <<"\t"/utf8>>, <<"\\t"/utf8>>). -file("src/cquill/dev.gleam", 734). ?DOC(" Format a single value for display\n"). -spec format_value(cquill@query@ast:value()) -> binary(). format_value(Value) -> case Value of {int_value, I} -> erlang:integer_to_binary(I); {float_value, F} -> gleam@string:inspect(F); {string_value, S} -> <<<<"\""/utf8, (escape_string(S))/binary>>/binary, "\""/utf8>>; {bool_value, B} -> gleam@bool:to_string(B); null_value -> <<"NULL"/utf8>>; {param_value, P} -> <<"$"/utf8, (erlang:integer_to_binary(P))/binary>>; {list_value, Values} -> Formatted = begin _pipe = Values, _pipe@1 = gleam@list:map(_pipe, fun format_value/1), gleam@string:join(_pipe@1, <<", "/utf8>>) end, <<<<"["/utf8, Formatted/binary>>/binary, "]"/utf8>> end. -file("src/cquill/dev.gleam", 709). ?DOC(" Format query parameters with sensitive field masking\n"). -spec format_params(list(cquill@query@ast:value()), list(binary()), binary()) -> binary(). format_params(Params, Mask_fields, Mask_pattern) -> Formatted = begin _pipe = Params, _pipe@1 = gleam@list:index_map( _pipe, fun(Param, _) -> Value_str = format_value(Param), case should_mask_value(Value_str, Mask_fields) of true -> Mask_pattern; false -> Value_str end end ), gleam@string:join(_pipe@1, <<", "/utf8>>) end, <<<<"["/utf8, Formatted/binary>>/binary, "]"/utf8>>. -file("src/cquill/dev.gleam", 776). ?DOC(" Analyze a query and provide optimization hints\n"). -spec analyze_query_for_hints(binary(), integer()) -> list(binary()). analyze_query_for_hints(Query, Row_count) -> Query_lower = string:lowercase(Query), Hints = [], Hints@1 = case gleam_stdlib:contains_string(Query_lower, <<"like '%"/utf8>>) of true -> lists:append( Hints, [<<"LIKE with leading wildcard '%...' cannot use indexes. Consider full-text search."/utf8>>] ); false -> Hints end, Hints@2 = case gleam_stdlib:contains_string( Query_lower, <<"select *"/utf8>> ) of true -> lists:append( Hints@1, [<<"SELECT * retrieves all columns. Consider selecting only needed columns."/utf8>>] ); false -> Hints@1 end, Hints@3 = case Row_count > 1000 of true -> lists:append( Hints@2, [<<<<"Large result set ("/utf8, (erlang:integer_to_binary(Row_count))/binary>>/binary, " rows). Consider pagination with LIMIT/OFFSET."/utf8>>] ); false -> Hints@2 end, Has_order_by = gleam_stdlib:contains_string( Query_lower, <<"order by"/utf8>> ), Has_limit = gleam_stdlib:contains_string(Query_lower, <<"limit"/utf8>>), Hints@4 = case (Has_order_by andalso not Has_limit) andalso (Row_count > 100) of true -> lists:append( Hints@3, [<<"ORDER BY without LIMIT on large results is expensive. Consider adding an index."/utf8>>] ); false -> Hints@3 end, Has_join = (gleam_stdlib:contains_string(Query_lower, <<" join "/utf8>>) orelse gleam_stdlib:contains_string(Query_lower, <<"inner join"/utf8>>)) orelse gleam_stdlib:contains_string(Query_lower, <<"left join"/utf8>>), Has_where = gleam_stdlib:contains_string(Query_lower, <<"where"/utf8>>), Hints@5 = case Has_join andalso not Has_where of true -> lists:append( Hints@4, [<<"JOIN without WHERE clause may return unexpected large results."/utf8>>] ); false -> Hints@4 end, Hints@6 = case (gleam_stdlib:contains_string( Query_lower, <<"where lower("/utf8>> ) orelse gleam_stdlib:contains_string(Query_lower, <<"where upper("/utf8>>)) orelse gleam_stdlib:contains_string(Query_lower, <<"where date("/utf8>>) of true -> lists:append( Hints@5, [<<"Functions in WHERE clause prevent index usage. Consider functional indexes."/utf8>>] ); false -> Hints@5 end, Hints@6. -file("src/cquill/dev.gleam", 528). ?DOC(" Slow query handler with helpful hints\n"). -spec dev_slow_query_handler(integer()) -> fun((cquill@telemetry:event(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> nil). dev_slow_query_handler(Threshold_ms) -> Threshold_us = Threshold_ms * 1000, fun(Event, _) -> case Event of {query_stop, E} -> case erlang:element(4, E) > Threshold_us of true -> Duration_ms = erlang:element(4, E) div 1000, gleam_stdlib:println_error( erlang:list_to_binary( [<<"[cquill] \x{26A0}\x{FE0F} SLOW QUERY ("/utf8>>, erlang:integer_to_binary(Duration_ms), <<"ms):"/utf8>>] ) ), gleam_stdlib:println_error( <<" "/utf8, (erlang:element(2, E))/binary>> ), gleam_stdlib:println_error( <<" rows: "/utf8, (erlang:integer_to_binary(erlang:element(5, E)))/binary>> ), Hints = analyze_query_for_hints( erlang:element(2, E), erlang:element(5, E) ), case Hints of [] -> nil; _ -> gleam_stdlib:println_error(<<""/utf8>>), gleam_stdlib:println_error( <<" Hints:"/utf8>> ), gleam@list:each( Hints, fun(Hint) -> gleam_stdlib:println_error( <<" - "/utf8, Hint/binary>> ) end ) end; false -> nil end; _ -> nil end end. -file("src/cquill/dev.gleam", 851). ?DOC(" Format an adapter error for display\n"). -spec format_error(cquill@error:adapter_error()) -> binary(). format_error(Err) -> case Err of not_found -> <<"Record not found"/utf8>>; {too_many_rows, Expected, Got} -> <<<<<<"Expected "/utf8, (erlang:integer_to_binary(Expected))/binary>>/binary, " row(s), got "/utf8>>/binary, (erlang:integer_to_binary(Got))/binary>>; {connection_failed, Reason} -> <<"Connection failed: "/utf8, Reason/binary>>; connection_timeout -> <<"Connection timeout"/utf8>>; pool_exhausted -> <<"Connection pool exhausted"/utf8>>; {connection_lost, Reason@1} -> <<"Connection lost: "/utf8, Reason@1/binary>>; {query_failed, Message, Code} -> <<<<<<"Query failed ["/utf8, (gleam@option:unwrap(Code, <<"?"/utf8>>))/binary>>/binary, "]: "/utf8>>/binary, Message/binary>>; {decode_failed, Row, Column, Expected@1, Got@1} -> <<<<<<<<<<<<<<<<"Decode failed at row "/utf8, (erlang:integer_to_binary(Row))/binary>>/binary, ", column "/utf8>>/binary, Column/binary>>/binary, " (expected "/utf8>>/binary, Expected@1/binary>>/binary, ", got "/utf8>>/binary, Got@1/binary>>/binary, ")"/utf8>>; timeout -> <<"Query timeout"/utf8>>; {unique_violation, Constraint, Detail} -> <<<<<<"Unique violation: "/utf8, Constraint/binary>>/binary, " - "/utf8>>/binary, Detail/binary>>; {foreign_key_violation, Constraint@1, Detail@1} -> <<<<<<"Foreign key violation: "/utf8, Constraint@1/binary>>/binary, " - "/utf8>>/binary, Detail@1/binary>>; {check_violation, Constraint@2, Detail@2} -> <<<<<<"Check violation: "/utf8, Constraint@2/binary>>/binary, " - "/utf8>>/binary, Detail@2/binary>>; {not_null_violation, Column@1} -> <<"NOT NULL violation: "/utf8, Column@1/binary>>; {constraint_violation, Constraint@3, Detail@3} -> <<<<<<"Constraint violation: "/utf8, Constraint@3/binary>>/binary, " - "/utf8>>/binary, Detail@3/binary>>; {stale_data, Expected@2, Actual} -> <<<<<<<<"Stale data (expected version "/utf8, Expected@2/binary>>/binary, ", got "/utf8>>/binary, Actual/binary>>/binary, ")"/utf8>>; {data_integrity_error, Message@1} -> <<"Data integrity error: "/utf8, Message@1/binary>>; {not_supported, Operation} -> <<"Not supported: "/utf8, Operation/binary>>; {adapter_specific, Code@1, Message@2} -> <<<<<<"Adapter error ["/utf8, Code@1/binary>>/binary, "]: "/utf8>>/binary, Message@2/binary>> end. -file("src/cquill/dev.gleam", 467). ?DOC(" Query logging handler with parameter masking\n"). -spec dev_query_handler(dev_config()) -> fun((cquill@telemetry:event(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())) -> nil). dev_query_handler(Config) -> fun(Event, _) -> case Event of {query_stop, E} -> Duration_ms = erlang:element(4, E) div 1000, Params_str = case erlang:element(4, Config) of true -> format_params( erlang:element(3, E), erlang:element(8, Config), erlang:element(9, Config) ); false -> <<""/utf8>> end, gleam_stdlib:println( erlang:list_to_binary( [<<"[cquill] "/utf8>>, erlang:element(2, E), <<" ["/utf8>>, erlang:integer_to_binary(Duration_ms), <<"ms, "/utf8>>, erlang:integer_to_binary(erlang:element(5, E)), <<" rows]"/utf8>>] ) ), case Params_str of <<""/utf8>> -> nil; _ -> gleam_stdlib:println( <<" params: "/utf8, Params_str/binary>> ) end; {query_exception, E@1} -> Duration_ms@1 = erlang:element(5, E@1) div 1000, Params_str@1 = case erlang:element(4, Config) of true -> format_params( erlang:element(3, E@1), erlang:element(8, Config), erlang:element(9, Config) ); false -> <<""/utf8>> end, gleam_stdlib:println_error( erlang:list_to_binary( [<<"[cquill] QUERY ERROR: "/utf8>>, erlang:element(2, E@1), <<" ["/utf8>>, erlang:integer_to_binary(Duration_ms@1), <<"ms]"/utf8>>] ) ), case Params_str@1 of <<""/utf8>> -> nil; _ -> gleam_stdlib:println_error( <<" params: "/utf8, Params_str@1/binary>> ) end, gleam_stdlib:println_error( <<" error: "/utf8, (format_error(erlang:element(4, E@1)))/binary>> ); _ -> nil end end. -file("src/cquill/dev.gleam", 391). ?DOC( " Attach telemetry handlers based on configuration.\n" " Telemetry attachment is fire-and-forget: failures don't prevent dev mode from working.\n" " This is intentional since telemetry is observability infrastructure, not core functionality.\n" ). -spec attach_handlers(dev_config()) -> {ok, nil} | {error, dev_error()}. attach_handlers(Config) -> case erlang:element(3, Config) of true -> _ = cquill@telemetry:attach( <<"cquill_dev_query"/utf8>>, [query_start_type, query_stop_type, query_exception_type], dev_query_handler(Config) ), nil; false -> nil end, _ = cquill@telemetry:attach( <<"cquill_dev_slow_query"/utf8>>, [query_stop_type], dev_slow_query_handler(erlang:element(5, Config)) ), case erlang:element(6, Config) of true -> _ = cquill@telemetry:attach( <<"cquill_dev_pool"/utf8>>, [pool_checkout_type, pool_checkin_type, pool_timeout_type], dev_pool_handler() ), nil; false -> nil end, _ = cquill@telemetry:attach( <<"cquill_dev_transaction"/utf8>>, [transaction_start_type, transaction_commit_type, transaction_rollback_type], dev_transaction_handler() ), {ok, nil}. -file("src/cquill/dev.gleam", 252). ?DOC(" Enable development mode with custom configuration\n"). -spec enable_with_config(dev_config()) -> {ok, nil} | {error, dev_error()}. enable_with_config(Config) -> case cquill@telemetry:start() of {ok, _} -> nil; {error, _} -> nil end, Server = case cquill_dev_ffi:get_dev_server() of {ok, S} -> {ok, S}; {error, _} -> case start_server() of {ok, S@1} -> cquill_dev_ffi:set_dev_server(S@1), {ok, S@1}; {error, _} -> {error, dev_mode_not_running} end end, case Server of {error, E} -> {error, E}; {ok, S@2} -> Result = gleam@erlang@process:call( S@2, 5000, fun(Reply_to) -> {enable, Config, Reply_to} end ), case Result of {ok, _} -> attach_handlers(Config); {error, E@1} -> {error, E@1} end end. -file("src/cquill/dev.gleam", 247). ?DOC(" Enable development mode with default configuration\n"). -spec enable() -> {ok, nil} | {error, dev_error()}. enable() -> enable_with_config(default_config()). -file("src/cquill/dev.gleam", 355). ?DOC( " Enable dev mode from environment variable\n" " Call this at application startup to auto-enable if CQUILL_DEV=1\n" ). -spec enable_from_env() -> {ok, nil} | {error, dev_error()}. enable_from_env() -> case cquill_dev_ffi:get_env(<<"CQUILL_DEV"/utf8>>) of {ok, Value} -> case Value of <<"1"/utf8>> -> enable(); <<"true"/utf8>> -> enable(); <<"yes"/utf8>> -> enable(); <<"on"/utf8>> -> enable(); _ -> {ok, nil} end; {error, _} -> {ok, nil} end. -file("src/cquill/dev.gleam", 454). ?DOC( " Detach all dev mode handlers.\n" " Detachment is fire-and-forget cleanup: failures are silently ignored.\n" " This ensures cleanup always completes, even if some handlers were never attached.\n" ). -spec detach_handlers() -> nil. detach_handlers() -> _ = cquill@telemetry:detach(<<"cquill_dev_query"/utf8>>), _ = cquill@telemetry:detach(<<"cquill_dev_slow_query"/utf8>>), _ = cquill@telemetry:detach(<<"cquill_dev_pool"/utf8>>), _ = cquill@telemetry:detach(<<"cquill_dev_transaction"/utf8>>), nil. -file("src/cquill/dev.gleam", 292). ?DOC(" Disable development mode\n"). -spec disable() -> {ok, nil} | {error, dev_error()}. disable() -> case cquill_dev_ffi:get_dev_server() of {error, _} -> {error, dev_mode_not_running}; {ok, Server} -> Result = gleam@erlang@process:call( Server, 5000, fun(Reply_to) -> {disable, Reply_to} end ), case Result of {ok, _} -> detach_handlers(), {ok, nil}; {error, E} -> {error, E} end end. -file("src/cquill/dev.gleam", 332). ?DOC(" Update configuration while dev mode is running\n"). -spec configure(dev_config()) -> {ok, nil} | {error, dev_error()}. configure(Config) -> case cquill_dev_ffi:get_dev_server() of {error, _} -> {error, dev_mode_not_running}; {ok, Server} -> Result = gleam@erlang@process:call( Server, 5000, fun(Reply_to) -> {update_config, Config, Reply_to} end ), case Result of {ok, _} -> detach_handlers(), attach_handlers(Config); {error, E} -> {error, E} end end. -file("src/cquill/dev.gleam", 368). ?DOC(" Stop the dev mode server completely\n"). -spec stop() -> nil. stop() -> _ = disable(), cquill_dev_ffi:clear_dev_server().