Are there special requirements for returns :map in RPC actions?

Hi folks I have a custom action that works perfectly in the backend (logs show correct data) but AshTypescript RPC returns empty {} to the frontend.
# In Fmma.Inspections.Inspection resource
action :validate_agent_location do
argument :agent_latitude, :decimal, allow_nil?: false
argument :agent_longitude, :decimal, allow_nil?: false
argument :school_id, :uuid, allow_nil?: false

returns :map

run fn input, _context ->
# GPS distance calculation logic
case validate_distance_logic(...) do
{:ok, validation_data} ->
{:ok, %{distance_meters: 42030.1, within_range: false, school_name: "..."}}
{:error, error_data} ->
{:ok, %{distance_meters: 42030.1, within_range: false, message: "..."}}
end
end
end
# In Fmma.Inspections.Inspection resource
action :validate_agent_location do
argument :agent_latitude, :decimal, allow_nil?: false
argument :agent_longitude, :decimal, allow_nil?: false
argument :school_id, :uuid, allow_nil?: false

returns :map

run fn input, _context ->
# GPS distance calculation logic
case validate_distance_logic(...) do
{:ok, validation_data} ->
{:ok, %{distance_meters: 42030.1, within_range: false, school_name: "..."}}
{:error, error_data} ->
{:ok, %{distance_meters: 42030.1, within_range: false, message: "..."}}
end
end
end
RPC Configuration:
# In domain typescript_rpc block
resource Fmma.Inspections.Inspection do
rpc_action :validate_location, :validate_agent_location
end
# In domain typescript_rpc block
resource Fmma.Inspections.Inspection do
rpc_action :validate_location, :validate_agent_location
end
Backend logs show correct data: %{distance_meters: 42030.1, within_range: false, ...} and action executes successfully (no crashes). Also API call reaches backend. But RPC response returns empty data: {"data": {}, "success": true} Are there special requirements for returns :map in RPC actions? Or am i doing json serialization correctly?
10 Replies
barnabasj
barnabasj2w ago
Wild guess, it could be because there is no type information for the keys on the map [8:16 PM] but I haven't looked at ash_typescript code yet. [8:17 PM] @Torkan will probably check in at some point. barnabasj — 8:25 PM both generic actions in the AshTypescript tests add constraints for the fields, so it could be that, but there also code for :map -> Record<string, any> [8:25 PM] But just for testing purposes you could add constraints for the :map to try if that makes it work. Like in this example https://github.com/ash-project/ash_typescript/blob/d83b16d0919ab7c6545b4c4e850233fb30c1751b/test/support/resources/org_todo.ex#L171-L188 GitHub ash_typescript/test/support/resources/org_todo.ex at d83b16d0919ab7... Automatic TypeScript type generation for Ash resources and actions - ash-project/ash_typescript [8:26 PM] also while it shouldn't change anything putting the return type at the top, next to the action name is the more common way to do it, instead of specificying the returns in the block
GitHub
ash_typescript/test/support/resources/org_todo.ex at d83b16d0919ab7...
Automatic TypeScript type generation for Ash resources and actions - ash-project/ash_typescript
barnabasj
barnabasj2w ago
Now I responded in the wrong thread 😅 I copied it over, doesn't look that nice now, sorry about that
Torkan
Torkan2w ago
Hm, I'll take a look 😅
Zeeshan
ZeeshanOP2w ago
Haha no probs, always something to learn 🫂
Torkan
Torkan2w ago
How does the call to validateAgentLocation look in your front-end code? or whatever it's rpc action name is set to
ZachDaniel
ZachDaniel2w ago
@Torkan we probably need to do a thing with :map returns and no fields where we just show everything
Torkan
Torkan2w ago
Yeah, agreed Adding constraints on it will definitely work though, I'd recommend doing that anyway @Zeeshan since it looks like you have a more or less fixed structure for that map, with some allow_nil? true fields And then we'll have to add some special casing for generic actions that return untyped composite types.. The generated functions shouldn't accept fields, and it should just return Record<string, any>
ZachDaniel
ZachDaniel2w ago
I think just any untyped composite type argument inputs and return values
Torkan
Torkan2w ago
Yes, inputs as well, although if we're lucky, those already work, I'll check soon after dealing with the returns first 😅 Ok, I've written a fix for this particular scenario now, but there are some other things that should also be addressed before it's released.. If you want to @Zeeshan you can try the main branch as a dependency in your project. When the types are regenerated that action will no longer accept the fields-arg, and the entire map will be returned in result.data
Zeeshan
ZeeshanOP2w ago
oh wow! it works 🚀 thanks for shipping muchas gracias 🫂
curl -X POST http://localhost:4000/rpc/run -H "Content-Type: application/json" -d '{"action": "validate_location", "input": {"agentLatitude": 12.8683213,
"agentLongitude": 74.8471483, "schoolId": "abb4d014-d206-488d-bec6-2ed493aa93b8"}}' | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 374 100 215 100 159 1949 1442 --:--:-- --:--:-- --:--:-- 3400
{
"data": {
"distanceMeters": 42030.12704079577,
"message": "Agent must be within 100m of school (currently 42030.1m away)",
"requiredRange": 100,
"schoolName": "Govt UP School Adkathbail",
"withinRange": false
},
"success": true
}
curl -X POST http://localhost:4000/rpc/run -H "Content-Type: application/json" -d '{"action": "validate_location", "input": {"agentLatitude": 12.8683213,
"agentLongitude": 74.8471483, "schoolId": "abb4d014-d206-488d-bec6-2ed493aa93b8"}}' | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 374 100 215 100 159 1949 1442 --:--:-- --:--:-- --:--:-- 3400
{
"data": {
"distanceMeters": 42030.12704079577,
"message": "Agent must be within 100m of school (currently 42030.1m away)",
"requiredRange": 100,
"schoolName": "Govt UP School Adkathbail",
"withinRange": false
},
"success": true
}

Did you find this page helpful?