-module(testcontainers_gleam). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/testcontainers_gleam.gleam"). -export([start_link/0, start_container/1, stop_container/1]). -export_type([container_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. ?MODULEDOC( " Gleam wrapper for the Elixir\n" " [testcontainers](https://hex.pm/packages/testcontainers) library.\n" "\n" " Provides functions to start and stop Docker containers in tests.\n" " Use `testcontainers_gleam/container` to build a container definition,\n" " then pass it to `start_container` to run it.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import testcontainers_gleam\n" " import testcontainers_gleam/container\n" "\n" " let c =\n" " container.new(\"redis:7.4-alpine\")\n" " |> container.with_exposed_port(6379)\n" "\n" " let assert Ok(running) = testcontainers_gleam.start_container(c)\n" " let id = container.container_id(running)\n" " let assert Ok(port) = container.mapped_port(running, 6379)\n" "\n" " let assert Ok(Nil) = testcontainers_gleam.stop_container(id)\n" " ```\n" ). -type container_error() :: {http_error, integer()} | failed_to_pull_image | failed_to_create_container | failed_to_start_container | failed_to_get_container | wait_strategy_failed | unknown. -file("src/testcontainers_gleam.gleam", 124). ?DOC(" Decode an error tuple from the Elixir library into a `ContainerError`.\n"). -spec decode_error(gleam@dynamic:dynamic_()) -> container_error(). decode_error(Raw) -> Tag_decoder = gleam@dynamic@decode:at([0], gleam@erlang@atom:decoder()), case gleam@dynamic@decode:run(Raw, Tag_decoder) of {ok, Tag} -> case erlang:atom_to_binary(Tag) of <<"http_error"/utf8>> -> Status_decoder = gleam@dynamic@decode:at( [1], {decoder, fun gleam@dynamic@decode:decode_int/1} ), Status = case gleam@dynamic@decode:run(Raw, Status_decoder) of {ok, S} -> S; {error, _} -> 0 end, {http_error, Status}; <<"failed_to_pull_image"/utf8>> -> failed_to_pull_image; <<"failed_to_create_container"/utf8>> -> failed_to_create_container; <<"failed_to_start_container"/utf8>> -> failed_to_start_container; <<"failed_to_get_container"/utf8>> -> failed_to_get_container; <<"log_wait_strategy"/utf8>> -> wait_strategy_failed; <<"command_wait_strategy"/utf8>> -> wait_strategy_failed; <<"port_wait_strategy"/utf8>> -> wait_strategy_failed; _ -> unknown end; {error, _} -> unknown end. -file("src/testcontainers_gleam.gleam", 59). ?DOC( " Start the Testcontainers GenServer.\n" "\n" " This is called automatically by `start_container`, so you only\n" " need to call it directly if you want to manage the lifecycle yourself.\n" " Returns `Ok(Nil)` if the GenServer was started or is already running.\n" ). -spec start_link() -> {ok, nil} | {error, container_error()}. start_link() -> case 'Elixir.Testcontainers':start_link() of {ok, _} -> {ok, nil}; {error, Raw} -> Tag_decoder = gleam@dynamic@decode:at( [0], gleam@erlang@atom:decoder() ), case gleam@dynamic@decode:run(Raw, Tag_decoder) of {ok, Tag} -> case erlang:atom_to_binary(Tag) of <<"already_started"/utf8>> -> {ok, nil}; _ -> {error, decode_error(Raw)} end; {error, _} -> {error, decode_error(Raw)} end end. -file("src/testcontainers_gleam.gleam", 91). ?DOC( " Start a container and wait until it is ready.\n" "\n" " Automatically starts the Testcontainers GenServer if it is not\n" " already running. Returns the started container on success, which\n" " can be queried with `container.container_id` and `container.mapped_port`.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let c =\n" " container.new(\"redis:7.4-alpine\")\n" " |> container.with_exposed_port(6379)\n" "\n" " let assert Ok(running) = testcontainers_gleam.start_container(c)\n" " ```\n" ). -spec start_container(testcontainers_gleam@container:container()) -> {ok, testcontainers_gleam@container:container()} | {error, container_error()}. start_container(Container) -> _ = 'Elixir.Testcontainers':start_link(), _pipe = Container, _pipe@1 = testcontainers_gleam_ffi:start_container(_pipe), gleam@result:map_error(_pipe@1, fun decode_error/1). -file("src/testcontainers_gleam.gleam", 106). ?DOC( " Stop a running container by its container ID.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let assert Ok(Nil) = testcontainers_gleam.stop_container(id)\n" " ```\n" ). -spec stop_container(binary()) -> {ok, nil} | {error, container_error()}. stop_container(Container_id) -> Raw = 'Elixir.Testcontainers':stop_container(Container_id), Decoded = begin _pipe = Raw, _pipe@1 = gleam@dynamic@decode:run(_pipe, gleam@erlang@atom:decoder()), gleam@result:'try'( _pipe@1, fun(Tag) -> case erlang:atom_to_binary(Tag) of <<"ok"/utf8>> -> {ok, nil}; _ -> {error, []} end end ) end, case Decoded of {ok, _} -> {ok, nil}; {error, _} -> {error, decode_error(Raw)} end.