-module(dream@http@params). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream/http/params.gleam"). -export([require_int/2, require_string/2, require_form/1, require_field/2, require_field_int/2, field_optional/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. ?MODULEDOC( " Parameter validation and extraction utilities\n" "\n" " This module provides safe parameter extraction from HTTP requests,\n" " returning Result types with dream.Error instead of crashing on missing or invalid data.\n" "\n" " Use these helpers to validate path parameters and form data in controllers,\n" " then pipe the results through your business logic using gleam/result.\n" ). -file("src/dream/http/params.gleam", 113). -spec parse_int_field(binary(), binary()) -> {ok, integer()} | {error, dream@http@error:error()}. parse_int_field(Value, Name) -> case gleam_stdlib:parse_int(Value) of {ok, I} -> {ok, I}; {error, _} -> {error, {bad_request, <<<<"Field '"/utf8, Name/binary>>/binary, "' must be an integer"/utf8>>}} end. -file("src/dream/http/params.gleam", 120). -spec result_string_to_error({ok, ADRS} | {error, binary()}) -> {ok, ADRS} | {error, dream@http@error:error()}. result_string_to_error(Result) -> case Result of {ok, Value} -> {ok, Value}; {error, Msg} -> {error, {bad_request, Msg}} end. -file("src/dream/http/params.gleam", 32). ?DOC( " Require a path parameter as an integer\n" "\n" " Returns a Result with dream.Error if the parameter is missing\n" " or cannot be converted to an integer.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " // Using with gleam/result pipeline\n" " let result = {\n" " use id <- result.try(params.require_int(request, \"id\"))\n" " // ... rest of logic with id : Int\n" " }\n" " ```\n" ). -spec require_int(dream@http@request:request(), binary()) -> {ok, integer()} | {error, dream@http@error:error()}. require_int(Req, Name) -> _pipe = dream@http@request:get_int_param(Req, Name), result_string_to_error(_pipe). -file("src/dream/http/params.gleam", 47). ?DOC( " Require a path parameter as a string\n" "\n" " Returns a Result with dream.Error if the parameter is missing.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " use name <- result.try(params.require_string(request, \"name\"))\n" " // ... rest of logic with name : String\n" " ```\n" ). -spec require_string(dream@http@request:request(), binary()) -> {ok, binary()} | {error, dream@http@error:error()}. require_string(Req, Name) -> _pipe = dream@http@request:get_string_param(Req, Name), result_string_to_error(_pipe). -file("src/dream/http/params.gleam", 192). -spec decode_url_component(binary()) -> binary(). decode_url_component(Component) -> With_spaces = gleam@string:replace(Component, <<"+"/utf8>>, <<" "/utf8>>), case gleam_stdlib:percent_decode(With_spaces) of {ok, Decoded} -> Decoded; {error, _} -> With_spaces end. -file("src/dream/http/params.gleam", 177). -spec parse_form_pair(binary()) -> gleam@option:option({binary(), binary()}). parse_form_pair(Pair) -> case gleam@string:split(Pair, <<"="/utf8>>) of [Key, Value] -> Decoded_key = decode_url_component(Key), Decoded_value = decode_url_component(Value), {some, {Decoded_key, Decoded_value}}; [Key@1] -> Decoded_key@1 = decode_url_component(Key@1), {some, {Decoded_key@1, <<""/utf8>>}}; _ -> none end. -file("src/dream/http/params.gleam", 167). -spec add_parsed_pair(binary(), list({binary(), binary()})) -> list({binary(), binary()}). add_parsed_pair(Pair, Rest_parsed) -> case parse_form_pair(Pair) of {some, Kv} -> [Kv | Rest_parsed]; none -> Rest_parsed end. -file("src/dream/http/params.gleam", 157). -spec parse_form_pairs(list(binary())) -> list({binary(), binary()}). parse_form_pairs(Pairs) -> case Pairs of [] -> []; [Pair | Rest] -> Rest_parsed = parse_form_pairs(Rest), add_parsed_pair(Pair, Rest_parsed) end. -file("src/dream/http/params.gleam", 150). -spec parse_form_body(binary()) -> list({binary(), binary()}). parse_form_body(Body) -> case Body of <<""/utf8>> -> []; _ -> parse_form_pairs(gleam@string:split(Body, <<"&"/utf8>>)) end. -file("src/dream/http/params.gleam", 63). ?DOC( " Require and parse form data from request body\n" "\n" " Returns a Result containing the parsed form data as key-value pairs.\n" " Returns an error if the body is empty or invalid.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " use form <- result.try(params.require_form(request))\n" " use title <- result.try(params.require_field(form, \"title\"))\n" " ```\n" ). -spec require_form(dream@http@request:request()) -> {ok, list({binary(), binary()})} | {error, dream@http@error:error()}. require_form(Req) -> case erlang:element(11, Req) of <<""/utf8>> -> {error, {bad_request, <<"Request body is empty"/utf8>>}}; Body -> {ok, parse_form_body(Body)} end. -file("src/dream/http/params.gleam", 203). -spec get_form_field(list({binary(), binary()}), binary()) -> gleam@option:option(binary()). get_form_field(Form_data, Name) -> _pipe = gleam@list:key_find(Form_data, Name), gleam@option:from_result(_pipe). -file("src/dream/http/params.gleam", 80). ?DOC( " Require a field from form data\n" "\n" " Returns an error if the field is missing or empty.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " use form <- result.try(params.require_form(request))\n" " use title <- result.try(params.require_field(form, \"title\"))\n" " ```\n" ). -spec require_field(list({binary(), binary()}), binary()) -> {ok, binary()} | {error, dream@http@error:error()}. require_field(Form, Name) -> case get_form_field(Form, Name) of {some, <<""/utf8>>} -> {error, {bad_request, <<<<"Field '"/utf8, Name/binary>>/binary, "' cannot be empty"/utf8>>}}; {some, Value} -> {ok, Value}; none -> {error, {bad_request, <<"Missing required field: "/utf8, Name/binary>>}} end. -file("src/dream/http/params.gleam", 102). ?DOC( " Require a field from form data as an integer\n" "\n" " Returns an error if the field is missing, empty, or not a valid integer.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " use form <- result.try(params.require_form(request))\n" " use priority <- result.try(params.require_field_int(form, \"priority\"))\n" " ```\n" ). -spec require_field_int(list({binary(), binary()}), binary()) -> {ok, integer()} | {error, dream@http@error:error()}. require_field_int(Form, Name) -> Result = begin gleam@result:'try'( require_field(Form, Name), fun(Value) -> parse_int_field(Value, Name) end ) end, Result. -file("src/dream/http/params.gleam", 137). ?DOC( " Extract an optional field from form data\n" "\n" " Returns None if the field is missing or empty, Some(value) otherwise.\n" " This never returns an error - use this for truly optional fields.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let description = params.field_optional(form, \"description\")\n" " ```\n" ). -spec field_optional(list({binary(), binary()}), binary()) -> gleam@option:option(binary()). field_optional(Form, Name) -> case get_form_field(Form, Name) of {some, <<""/utf8>>} -> none; {some, Value} -> {some, Value}; none -> none end.