AshTypescript provides features to improve developer experience: namespace organization, JSDoc generation, and API manifest documentation.
Namespaces organize RPC actions into logical groups, improving discoverability in large codebases.
Namespaces can be configured at three levels with cascading precedence:
Domain Level - Default namespace for all resources in a domain:
defmodule MyApp.Domain do
use Ash.Domain, extensions: [AshTypescript.Rpc]
typescript_rpc do
namespace :api # All resources default to "api" namespace
resource MyApp.Todo do
rpc_action :list_todos, :read
end
end
endResource Level - Override for all actions on a specific resource:
typescript_rpc do
namespace :api
resource MyApp.Todo do
namespace :todos # Overrides domain namespace
rpc_action :list_todos, :read
rpc_action :create_todo, :create
end
resource MyApp.User do
# Uses domain namespace "api"
rpc_action :list_users, :read
end
endAction Level - Override for a specific action:
typescript_rpc do
namespace :api
resource MyApp.Todo do
namespace :todos
rpc_action :list_todos, :read # Uses "todos"
rpc_action :admin_list, :read, namespace: :admin # Uses "admin"
end
endAction namespace > Resource namespace > Domain namespace > nil
With namespaces enabled, the generated JSDoc includes the namespace:
/**
* List all todos
*
* @ashActionType :read
* @namespace todos
*/
export async function listTodos(...) { ... }Generated TypeScript functions include JSDoc comments that provide IDE discoverability through hover documentation and autocomplete hints.
Every generated RPC function includes basic JSDoc:
/**
* List all todos
*
* @ashActionType :read
*/
export async function listTodos(...) { ... }Enable detailed Ash metadata in JSDoc for development:
config :ash_typescript,
add_ash_internals_to_jsdoc: trueThis adds internal references:
/**
* List all todos
*
* @ashActionType :read
* @ashResource MyApp.Todo
* @ashAction :list_todos
* @ashActionDef lib/my_app/resources/todo.ex
* @rpcActionDef lib/my_app/domain.ex
* @namespace todos
*/
export async function listTodos(...) { ... }| Tag | Description | When Shown |
|---|---|---|
@ashActionType |
Ash action type (:read, :create, etc.) |
Always |
@ashResource |
Full Elixir module name | When add_ash_internals_to_jsdoc: true |
@ashAction |
Internal Ash action name | When add_ash_internals_to_jsdoc: true |
@ashActionDef |
Source file of Ash action definition | When add_ash_internals_to_jsdoc: true |
@rpcActionDef |
Source file of RPC action configuration | When add_ash_internals_to_jsdoc: true |
@namespace |
Action namespace | When namespace is configured |
@see |
Related actions | When see: option is configured |
@deprecated |
Deprecation notice | When deprecated: option is configured |
For monorepo setups where Elixir code is in a subdirectory:
config :ash_typescript,
source_path_prefix: "backend"Output:
/**
* @ashActionDef backend/lib/my_app/resources/todo.ex
* @rpcActionDef backend/lib/my_app/domain.ex
*/Override default descriptions per action:
typescript_rpc do
resource MyApp.Todo do
rpc_action :list_todos, :read,
description: "Fetch all todos for the current user"
end
endWhen add_ash_internals_to_jsdoc: true, the Ash action's description is used as fallback if no RPC description is set.
Link related actions in JSDoc using the see option:
rpc_action :list_todos, :read,
see: [:create_todo, :update_todo]Output:
/**
* @see createTodo
* @see updateTodo
*/Mark actions as deprecated:
rpc_action :old_list, :read,
deprecated: true
rpc_action :legacy_list, :read,
deprecated: "Use listTodos instead"Output:
/**
* @deprecated
*/
/**
* @deprecated Use listTodos instead
*/Generate a Markdown manifest documenting all RPC actions for API documentation and developer onboarding.
config :ash_typescript,
manifest_file: "./docs/RPC_MANIFEST.md",
add_ash_internals_to_manifest: true# RPC Action Manifest
Generated: 2025-01-15
## Namespace: todos
### Todo
| Function | Action Type | Ash Action | Resource | Validation | Zod Schema | Channel |
|----------|-------------|------------|----------|------------|------------|---------|
| `listTodos` | read | `list` | `MyApp.Todo` | `validateListTodos` | `ListTodosInputSchema` | `listTodosChannel` |
| `createTodo` | create | `create` | `MyApp.Todo` | `validateCreateTodo` | `CreateTodoInputSchema` | `createTodoChannel` |
- **`listTodos`**: Fetch all todos for the current user
- **`createTodo`**: Create a new Todo | **See also:** `listTodos`
**Typed Queries:**
- `todoFields` -> `TodoFieldsResult`: Pre-defined field selection- With namespaces: Actions grouped by namespace
- Without namespaces: Actions grouped by domain
The add_ash_internals_to_manifest config controls whether internal Ash details are shown:
| Setting | Columns Shown |
|---|---|
false |
Function, Action Type |
true |
Function, Action Type, Ash Action, Resource |
config :ash_typescript,
# JSDoc configuration
add_ash_internals_to_jsdoc: false, # Show Ash module/action details
source_path_prefix: nil, # Prefix for source paths (monorepos)
# Manifest configuration
manifest_file: nil, # Path to generate manifest (nil = disabled)
add_ash_internals_to_manifest: false # Show Ash details in manifestDevelopment Configuration:
# config/dev.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: true,
add_ash_internals_to_manifest: true,
manifest_file: "./docs/RPC_MANIFEST.md"Production Configuration:
# config/prod.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: false,
add_ash_internals_to_manifest: falsetypescript_rpc do
resource MyApp.Todo do
namespace :todos
rpc_action :list_todos, :read
rpc_action :create_todo, :create
end
resource MyApp.User do
namespace :users
rpc_action :list_users, :read
rpc_action :get_current_user, :get_current, namespace: :auth
end
resource MyApp.Session do
namespace :auth
rpc_action :login, :create
rpc_action :logout, :destroy
end
end# config/config.exs
config :ash_typescript,
add_ash_internals_to_jsdoc: Mix.env() == :dev,
add_ash_internals_to_manifest: Mix.env() == :dev# backend/config/config.exs
config :ash_typescript,
source_path_prefix: "backend",
output_file: "../frontend/src/generated/ash_rpc.ts"- RPC Action Options - All action configuration options
- Configuration Reference - Complete configuration options
- Lifecycle Hooks - HTTP and channel lifecycle hooks