Current section

Files

Jump to
oaspec src oaspec@codegen@writer.erl
Raw

src/oaspec@codegen@writer.erl

-module(oaspec@codegen@writer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/oaspec/codegen/writer.gleam").
-export([write_all/3, resolve_paths/2, expected_paths/2, output_dirs/1, error_to_string/1]).
-export_type([write_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 write_error() :: {directory_create_error, binary(), binary()} |
{file_write_error, binary(), binary()}.
-file("src/oaspec/codegen/writer.gleam", 57).
?DOC(" Ensure a directory exists, creating it if necessary.\n").
-spec ensure_directory(binary()) -> {ok, nil} | {error, write_error()}.
ensure_directory(Path) ->
_pipe = simplifile:create_directory_all(Path),
gleam@result:map_error(
_pipe,
fun(Err) ->
{directory_create_error,
Path,
<<"Failed to create directory: "/utf8,
(simplifile:describe_error(Err))/binary>>}
end
).
-file("src/oaspec/codegen/writer.gleam", 73).
?DOC(
" Write a list of generated files to a directory.\n"
"\n"
" Issue #247: files marked `SkipIfExists` (currently `handlers.gleam`)\n"
" are written only on first generation. If the file already exists on\n"
" disk, it is left alone — the user owns the contents and the\n"
" generator must not clobber their implementation.\n"
).
-spec write_files(
list(oaspec@codegen@context:generated_file()),
binary(),
list(binary()),
fun((binary()) -> nil)
) -> {ok, list(binary())} | {error, write_error()}.
write_files(Files, Base_path, Written, On_write) ->
gleam@list:try_fold(
Files,
Written,
fun(Acc, File) ->
Full_path = <<<<Base_path/binary, "/"/utf8>>/binary,
(erlang:element(2, File))/binary>>,
case {erlang:element(5, File), simplifile_erl:is_file(Full_path)} of
{skip_if_exists, {ok, true}} ->
{ok, Acc};
{_, _} ->
gleam@result:'try'(
begin
_pipe = simplifile:write(
Full_path,
erlang:element(3, File)
),
gleam@result:map_error(
_pipe,
fun(Err) ->
{file_write_error,
Full_path,
<<"Failed to write file: "/utf8,
(simplifile:describe_error(Err))/binary>>}
end
)
end,
fun(_) ->
On_write(Full_path),
{ok, [Full_path | Acc]}
end
)
end
end
).
-file("src/oaspec/codegen/writer.gleam", 14).
?DOC(" Write pre-generated files to disk based on configuration.\n").
-spec write_all(
list(oaspec@codegen@context:generated_file()),
oaspec@config:config(),
fun((binary()) -> nil)
) -> {ok, list(binary())} | {error, write_error()}.
write_all(Files, Cfg, On_write) ->
Shared_files = gleam@list:filter(
Files,
fun(F) -> erlang:element(4, F) =:= shared_target end
),
Server_files = gleam@list:filter(
Files,
fun(F@1) -> erlang:element(4, F@1) =:= server_target end
),
Client_files = gleam@list:filter(
Files,
fun(F@2) -> erlang:element(4, F@2) =:= client_target end
),
Server_path = oaspec@config:output_server(Cfg),
Client_path = oaspec@config:output_client(Cfg),
Written_files = [],
gleam@result:'try'(case oaspec@config:mode(Cfg) of
server ->
gleam@result:'try'(
ensure_directory(Server_path),
fun(_) ->
_pipe = write_files(
Shared_files,
Server_path,
Written_files,
On_write
),
gleam@result:'try'(
_pipe,
fun(W) ->
write_files(
Server_files,
Server_path,
W,
On_write
)
end
)
end
);
both ->
gleam@result:'try'(
ensure_directory(Server_path),
fun(_) ->
_pipe = write_files(
Shared_files,
Server_path,
Written_files,
On_write
),
gleam@result:'try'(
_pipe,
fun(W) ->
write_files(
Server_files,
Server_path,
W,
On_write
)
end
)
end
);
client ->
{ok, Written_files}
end, fun(Written_files@1) ->
gleam@result:'try'(case oaspec@config:mode(Cfg) of
client ->
gleam@result:'try'(
ensure_directory(Client_path),
fun(_) ->
_pipe@1 = write_files(
Shared_files,
Client_path,
Written_files@1,
On_write
),
gleam@result:'try'(
_pipe@1,
fun(W@1) ->
write_files(
Client_files,
Client_path,
W@1,
On_write
)
end
)
end
);
both ->
gleam@result:'try'(
ensure_directory(Client_path),
fun(_) ->
_pipe@1 = write_files(
Shared_files,
Client_path,
Written_files@1,
On_write
),
gleam@result:'try'(
_pipe@1,
fun(W@1) ->
write_files(
Client_files,
Client_path,
W@1,
On_write
)
end
)
end
);
server ->
{ok, Written_files@1}
end, fun(Written_files@2) -> {ok, Written_files@2} end)
end).
-file("src/oaspec/codegen/writer.gleam", 112).
?DOC(
" Resolve generated files to their full output paths and content.\n"
" Used by --check to compare against existing files without writing.\n"
"\n"
" Issue #247: `SkipIfExists` files (e.g. user-owned `handlers.gleam`)\n"
" are dropped from the result. `--check` is meant to flag drift in\n"
" generator-owned files; user-edited files are expected to differ\n"
" from the bootstrap stub and should not be reported as out-of-date.\n"
).
-spec resolve_paths(
list(oaspec@codegen@context:generated_file()),
oaspec@config:config()
) -> list({binary(), binary()}).
resolve_paths(Files, Cfg) ->
Files@1 = gleam@list:filter(
Files,
fun(F) -> erlang:element(5, F) /= skip_if_exists end
),
Shared_files = gleam@list:filter(
Files@1,
fun(F@1) -> erlang:element(4, F@1) =:= shared_target end
),
Server_files = gleam@list:filter(
Files@1,
fun(F@2) -> erlang:element(4, F@2) =:= server_target end
),
Client_files = gleam@list:filter(
Files@1,
fun(F@3) -> erlang:element(4, F@3) =:= client_target end
),
Server_path = oaspec@config:output_server(Cfg),
Client_path = oaspec@config:output_client(Cfg),
Server_entries = case oaspec@config:mode(Cfg) of
server ->
gleam@list:map(
lists:append(Shared_files, Server_files),
fun(F@4) ->
{<<<<Server_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@4))/binary>>,
erlang:element(3, F@4)}
end
);
both ->
gleam@list:map(
lists:append(Shared_files, Server_files),
fun(F@4) ->
{<<<<Server_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@4))/binary>>,
erlang:element(3, F@4)}
end
);
client ->
[]
end,
Client_entries = case oaspec@config:mode(Cfg) of
client ->
gleam@list:map(
lists:append(Shared_files, Client_files),
fun(F@5) ->
{<<<<Client_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@5))/binary>>,
erlang:element(3, F@5)}
end
);
both ->
gleam@list:map(
lists:append(Shared_files, Client_files),
fun(F@5) ->
{<<<<Client_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@5))/binary>>,
erlang:element(3, F@5)}
end
);
server ->
[]
end,
lists:append(Server_entries, Client_entries).
-file("src/oaspec/codegen/writer.gleam", 150).
?DOC(
" Every file path the generator would write for the given config — including\n"
" `SkipIfExists` files. Used by `--check` to keep user-owned `handlers.gleam`\n"
" off the orphan list while still excluding it from byte-comparison drift\n"
" reports (`resolve_paths` drops `SkipIfExists` entries).\n"
).
-spec expected_paths(
list(oaspec@codegen@context:generated_file()),
oaspec@config:config()
) -> list(binary()).
expected_paths(Files, Cfg) ->
Shared_files = gleam@list:filter(
Files,
fun(F) -> erlang:element(4, F) =:= shared_target end
),
Server_files = gleam@list:filter(
Files,
fun(F@1) -> erlang:element(4, F@1) =:= server_target end
),
Client_files = gleam@list:filter(
Files,
fun(F@2) -> erlang:element(4, F@2) =:= client_target end
),
Server_path = oaspec@config:output_server(Cfg),
Client_path = oaspec@config:output_client(Cfg),
Server_entries = case oaspec@config:mode(Cfg) of
server ->
gleam@list:map(
lists:append(Shared_files, Server_files),
fun(F@3) ->
<<<<Server_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@3))/binary>>
end
);
both ->
gleam@list:map(
lists:append(Shared_files, Server_files),
fun(F@3) ->
<<<<Server_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@3))/binary>>
end
);
client ->
[]
end,
Client_entries = case oaspec@config:mode(Cfg) of
client ->
gleam@list:map(
lists:append(Shared_files, Client_files),
fun(F@4) ->
<<<<Client_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@4))/binary>>
end
);
both ->
gleam@list:map(
lists:append(Shared_files, Client_files),
fun(F@4) ->
<<<<Client_path/binary, "/"/utf8>>/binary,
(erlang:element(2, F@4))/binary>>
end
);
server ->
[]
end,
lists:append(Server_entries, Client_entries).
-file("src/oaspec/codegen/writer.gleam", 184).
?DOC(" Return the output directories that would be written to for the given config.\n").
-spec output_dirs(oaspec@config:config()) -> list(binary()).
output_dirs(Cfg) ->
case oaspec@config:mode(Cfg) of
server ->
[oaspec@config:output_server(Cfg)];
client ->
[oaspec@config:output_client(Cfg)];
both ->
[oaspec@config:output_server(Cfg), oaspec@config:output_client(Cfg)]
end.
-file("src/oaspec/codegen/writer.gleam", 193).
?DOC(" Convert a write error to a human-readable string.\n").
-spec error_to_string(write_error()) -> binary().
error_to_string(Error) ->
case Error of
{directory_create_error, Path, Detail} ->
<<<<<<"Failed to create directory "/utf8, Path/binary>>/binary,
": "/utf8>>/binary,
Detail/binary>>;
{file_write_error, Path@1, Detail@1} ->
<<<<<<"Failed to write file "/utf8, Path@1/binary>>/binary,
": "/utf8>>/binary,
Detail@1/binary>>
end.