Skip to content

Commit 7701bc7

Browse files
authored
Merge pull request #56 from barnabasJ/fix-array-map-return-type
fix(codegen): generate Array<Record<string, any>> for {:array, :map} return types
2 parents a67be0d + e6f0e14 commit 7701bc7

File tree

7 files changed

+73
-7
lines changed

7 files changed

+73
-7
lines changed

lib/ash_typescript/rpc/codegen/function_generators/function_core.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ defmodule AshTypescript.Rpc.Codegen.FunctionGenerators.FunctionCore do
148148
{updated_fields, true,
149149
"Fields extends #{rpc_action_name_pascal}Fields | undefined = undefined"}
150150

151-
{:ok, :unconstrained_map, _} ->
151+
{:ok, type, _} when type in [:unconstrained_map, :array_of_unconstrained_map] ->
152152
# Unconstrained maps don't support field selection
153153
{config_fields, false, nil}
154154

lib/ash_typescript/rpc/codegen/helpers/action_introspection.ex

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ defmodule AshTypescript.Rpc.Codegen.Helpers.ActionIntrospection do
144144
- `{:ok, :typed_struct, {module, fields}}` - Type with field constraints (TypedStruct or similar)
145145
- `{:ok, :array_of_typed_struct, {module, fields}}` - Array of types with field constraints
146146
- `{:ok, :unconstrained_map, nil}` - Map without field constraints
147+
- `{:ok, :array_of_unconstrained_map, nil}` - Array of maps without field constraints
147148
- `{:error, :not_generic_action}` - Not a generic action
148149
- `{:error, reason}` - Other errors
149150
"""
@@ -181,7 +182,11 @@ defmodule AshTypescript.Rpc.Codegen.Helpers.ActionIntrospection do
181182
end
182183

183184
:unconstrained_map ->
184-
{:ok, :unconstrained_map, nil}
185+
if is_array do
186+
{:ok, :array_of_unconstrained_map, nil}
187+
else
188+
{:ok, :unconstrained_map, nil}
189+
end
185190

186191
{:error, reason} ->
187192
{:error, reason}

lib/ash_typescript/rpc/codegen/type_generators/result_types.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ defmodule AshTypescript.Rpc.Codegen.TypeGenerators.ResultTypes do
315315
export type Infer#{rpc_action_name_pascal}Result = Record<string, any>;
316316
"""
317317

318+
{:ok, :array_of_unconstrained_map, _} ->
319+
"""
320+
export type Infer#{rpc_action_name_pascal}Result = Array<Record<string, any>>;
321+
"""
322+
318323
_ ->
319324
if action.returns do
320325
return_type = get_ts_type(%{type: action.returns, constraints: action.constraints})

lib/ash_typescript/rpc/pipeline.ex

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ defmodule AshTypescript.Rpc.Pipeline do
982982
when type in [:typed_map, :array_of_typed_map, :typed_struct, :array_of_typed_struct] ->
983983
format_generic_action_output(data, action, formatter)
984984

985-
{:ok, :unconstrained_map, _} ->
985+
{:ok, type, _} when type in [:unconstrained_map, :array_of_unconstrained_map] ->
986986
format_field_names(data, formatter)
987987

988988
_ ->
@@ -1000,7 +1000,7 @@ defmodule AshTypescript.Rpc.Pipeline do
10001000

10011001
defp unconstrained_map_action?(action) do
10021002
case ActionIntrospection.action_returns_field_selectable_type?(action) do
1003-
{:ok, :unconstrained_map, _} -> true
1003+
{:ok, type, _} when type in [:unconstrained_map, :array_of_unconstrained_map] -> true
10041004
_ -> false
10051005
end
10061006
end
@@ -1019,9 +1019,14 @@ defmodule AshTypescript.Rpc.Pipeline do
10191019

10201020
:action ->
10211021
case ActionIntrospection.action_returns_field_selectable_type?(action) do
1022-
{:ok, :unconstrained_map, _} -> false
1023-
{:ok, _, _} -> true
1024-
_ -> false
1022+
{:ok, type, _} when type in [:unconstrained_map, :array_of_unconstrained_map] ->
1023+
false
1024+
1025+
{:ok, _, _} ->
1026+
true
1027+
1028+
_ ->
1029+
false
10251030
end
10261031

10271032
_ ->

test/ash_typescript/rpc/rpc_run_action_generic_actions_test.exs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,46 @@ defmodule AshTypescript.Rpc.RpcRunActionGenericActionsTest do
504504
end
505505
end
506506

507+
describe "get_custom_data_list action (array of unconstrained maps)" do
508+
setup do
509+
conn = TestHelpers.build_rpc_conn()
510+
%{conn: conn}
511+
end
512+
513+
test "returns array of maps", %{conn: conn} do
514+
result =
515+
Rpc.run_action(:ash_typescript, conn, %{
516+
"action" => "get_custom_data_list_todo"
517+
})
518+
519+
assert result["success"] == true
520+
data = result["data"]
521+
522+
assert is_list(data)
523+
assert length(data) == 2
524+
525+
[first, second] = data
526+
assert first["userId"] == "123e4567-e89b-12d3-a456-426614174000"
527+
assert first["status"] == "active"
528+
assert second["userId"] == "223e4567-e89b-12d3-a456-426614174001"
529+
assert second["status"] == "pending"
530+
end
531+
532+
test "generated result type is Array<Record<string, any>>" do
533+
{:ok, typescript} = AshTypescript.Rpc.Codegen.generate_typescript_types(:ash_typescript)
534+
535+
assert typescript =~
536+
"export type InferGetCustomDataListTodoResult = Array<Record<string, any>>;"
537+
end
538+
539+
test "non-array unconstrained map result type remains Record<string, any>" do
540+
{:ok, typescript} = AshTypescript.Rpc.Codegen.generate_typescript_types(:ash_typescript)
541+
542+
assert typescript =~
543+
"export type InferGetCustomDataTodoResult = Record<string, any>;"
544+
end
545+
end
546+
507547
describe "complex return type validation" do
508548
setup do
509549
conn = TestHelpers.build_rpc_conn()

test/support/domain.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ defmodule AshTypescript.Test.Domain do
7575
rpc_action :get_keyword_options_todo, :get_keyword_options
7676
rpc_action :get_coordinates_info_todo, :get_coordinates_info
7777
rpc_action :get_custom_data_todo, :get_custom_data
78+
rpc_action :get_custom_data_list_todo, :get_custom_data_list
7879
rpc_action :destroy_todo, :destroy
7980
rpc_action :assign_to_user_todo, :assign_to_user
8081
rpc_action :assign_to_users_todo, :assign_to_users

test/support/resources/todo.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,16 @@ defmodule AshTypescript.Test.Todo do
664664
end
665665
end
666666

667+
action :get_custom_data_list, {:array, :map} do
668+
run fn _input, _context ->
669+
{:ok,
670+
[
671+
%{user_id: "123e4567-e89b-12d3-a456-426614174000", status: "active"},
672+
%{user_id: "223e4567-e89b-12d3-a456-426614174001", status: "pending"}
673+
]}
674+
end
675+
end
676+
667677
# Additional read action with different pagination configuration for testing
668678
read :search_paginated do
669679
argument :query, :string, allow_nil?: false

0 commit comments

Comments
 (0)