AshIntrospection.Rpc.Pipeline (AshIntrospection v0.3.0)
View SourceLanguage-agnostic four-stage RPC pipeline for Ash actions.
Implements the core pipeline stages:
- parse_request/3 - Parse and validate input with fail-fast
- execute_ash_action/2 - Execute Ash operations
- process_result/3 - Apply field selection
- format_output/3 - Format for client consumption
Configuration
The pipeline is configured via a config map that provides all the language-specific behavior through callbacks:
%{
input_field_formatter: :camel_case,
output_field_formatter: :camel_case,
field_names_callback: :interop_field_names,
get_original_field_name: fn resource, client_key -> ... end,
format_field_for_client: fn field_name, resource, formatter -> ... end,
discover_action: fn otp_app, params -> ... end,
not_found_error?: true
}Usage
Language-specific wrappers (e.g., AshTypescript.Rpc.Pipeline) should:
- Build the config map with their specific callbacks
- Call the shared pipeline functions with that config
- Handle any language-specific pre/post processing
This allows each language generator to customize the behavior while sharing the core pipeline logic.
Summary
Functions
Stage 2: Execute Ash action using the parsed request.
Stage 4: Format output for client consumption.
Stage 4: Format output for client consumption with type awareness.
Formats a sort string by converting field names from client format to internal format.
Stage 3: Filter result fields using the extraction template.
Types
@type config() :: %{ optional(:input_field_formatter) => atom(), optional(:output_field_formatter) => atom(), optional(:field_names_callback) => atom(), optional(:get_original_field_name) => (module(), String.t() -> atom() | nil), optional(:format_field_for_client) => (atom(), module() | nil, atom() -> String.t()), optional(:not_found_error?) => boolean() }
Functions
@spec execute_ash_action(AshIntrospection.Rpc.Request.t(), config()) :: {:ok, term()} | {:error, term()}
Stage 2: Execute Ash action using the parsed request.
Builds the appropriate Ash query/changeset and executes it. Returns the raw Ash result for further processing.
Stage 4: Format output for client consumption.
Applies output field formatting and final response structure.
The error clause covers failures raised before a %Request{} exists — action
discovery, identity resolution, parameter validation. It formats them exactly
as format_output_with_request/3 does, so both entry points hand the client
the same response shape and the same client-resolvable placeholders.
@spec format_output_with_request(term(), AshIntrospection.Rpc.Request.t(), config()) :: term()
Stage 4: Format output for client consumption with type awareness.
Applies type-aware output field formatting and final response structure.
Formats a sort string by converting field names from client format to internal format.
Handles Ash.Query.sort_input format:
- "name" or "+name" (ascending)
- "++name" (ascending with nils first)
- "-name" (descending)
- "--name" (descending with nils last)
- "-name,++title" (multiple fields with different modifiers)
Preserves sort modifiers while converting field names using the input formatter.
Examples
iex> format_sort_string("--startDate,++insertedAt", :camel_case)
"--start_date,++inserted_at"
iex> format_sort_string("-userName", :camel_case)
"-user_name"
iex> format_sort_string(nil, :camel_case)
nil
@spec process_result(term(), AshIntrospection.Rpc.Request.t(), config()) :: {:ok, term()} | {:error, term()}
Stage 3: Filter result fields using the extraction template.
Applies field selection to the Ash result using the pre-computed template. Performance-optimized single-pass filtering. Handles metadata extraction for both read and mutation actions.